简体   繁体   中英

Foreach inside array.map()

I'm trying to map values to a new array. The problem is that the property that I'm mapping can either be a number or an array.

I have a problem when it comes to arrays, because my result is an associative array. My goal is to turn [[1,2,3], [1,2,3]] (see below) in to [1,2,3,1,2,3] . In other words; just make it a one dimensional array.

I've tried with a foreach loop inside the map(), without success. Any ideas?

var list = [{ foo: 1, bar: [1,2,3] }, { foo: 2, bar: [1,2,3] }];

var retArr = list.map(function (v) {

    return v.bar;

});

console.log(retArr); // [[1,2,3], [1,2,3]]

var list = [{ foo: 1, bar: [1,2,3] }, { foo: 2, bar: [1,2,3] }];

var retArr = list.map(function (v) {

    if($.isArray(v.bar)){

        $.each(v.bar, function(i, v){

            return v;
        });

    } else {

        return v.bar;
    }
});

console.log(retArr); // [undefined, undefined] 

http://jsfiddle.net/Mck7N/

If you use jQuery's map function , you get array flattening automatically:

The function can return [...] an array of values, which will be flattened into the full array

var retArr = $.map(list, function (v) {
    return v.bar;
});

In your second example, you get [undefined, undefined] as result because you are not returning a value from the callback. The return value of the $.each callback has no influence on the return value of the .map callback.

And .map wouldn't have helped you here, since you can only return one value from the callback. Instead you could just iterate over the array:

var retArr = [];

list.forEach(function (v) {
    if ($.isArray(v.bar)) {
        retArray.push.apply(retArray, v.bar);
    } 
    else {
        retArray.push(v.bar);
    }
});

Alternatively, you could use Array#reduce . But since you are using jQuery anyway, using its map function is the easiest solution.

Without JQuery you can also flatten using Array.reduce :

var list = [{ foo: 1, bar: [1,2,3] }, { foo: 2, bar: [1,2,3] }]
   ,retArr = list.reduce(function (a,b) {
                 return a.concat(b.bar);
               },[]
           );
//=> retArr = [1,2,3,1,2,3]

You cannot use map alone, since that would only return an array of arrays or numbers. Yet, you can flatten that into one array by using concat :

var retArr = [].concat.apply([], list.map(function(v) { return v.bar; }));

If you used Underscore , you can even shorten that into

var retArr = _.flatten(_.pluck(list, "bar"), true);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM