0

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/

0

3 Answers 3

4

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.

Sign up to request clarification or add additional context in comments.

1 Comment

I had no idea that it was called "flatting". If I did, I probably would have found it :-) Thanks
2

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]

2 Comments

In your first example the return value of map is never used so you should replace map with forEach which does the same but returns nothing. Also you can delete "return v;". In your second example you set the global variable retArr to [] and afterwards you call map. Global variables should be avoided if possible.
@SpiderPig: you're partly right. Changed the answer to using Array.reduce, which gives the OP a one liner.
0

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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.