13

I've got array of objects, where I take only locations array. My goal is to merge these locations array to one array, however I fail to do so and get empty array. This is how I do it:

let results = [{
    id: '1',
    locations: ['aaaa', 'bbbbbb', 'cccccc']
  },
  {
    id: '2',
    locations: []
  },
  {
    id: '3',
    locations: ['ddd', 'aaadsad', 'sefd']
  },
  {
    id: '4',
    locations: ['ffff', 'eeee', 'sfdsfsd']
  },
];
const locationIds = [].concat.apply([], ...results.filter(s => s.locations && s.locations.length > 0).map(({
  locations
}) => ({
  locations
})));

console.log(locationIds);

what I am doing wrong here? The result should be ['aaaa', 'bbbbbb', 'cccccc', 'ddd', 'aaadsad', 'sefd', 'ffff', 'eeee', 'sfdsfsd'];

user122222
  • 2,179
  • 4
  • 35
  • 78

5 Answers5

8

You don't need filter here. Just use map method by passing a callback provided function which is applied for every item on the array.

let results = [{ id: '1', locations: ['aaaa', 'bbbbbb', 'cccccc'] }, { id: '2', locations: [] }, { id: '3', locations: ['ddd', 'aaadsad', 'sefd'] }, { id: '4', locations: ['ffff', 'eeee', 'sfdsfsd'] }, ];

const locationIds = [].concat(...results.map(s => s.locations));

console.log(locationIds);
Mihai Alexandru-Ionut
  • 47,092
  • 13
  • 101
  • 128
  • 1
    @user122222, you're welcome! You could create your own implementation of `flatMap` like here: https://stackoverflow.com/questions/39837678/why-no-array-prototype-flatmap-in-javascript/47549603 – Mihai Alexandru-Ionut Feb 01 '20 at 10:25
6

You can try with flatMap():

The flatMap() method first maps each element using a mapping function, then flattens the result into a new array. It is identical to a map() followed by a flat() of depth 1, but flatMap() is often quite useful, as merging both into one method is slightly more efficient.

let results = [{
    id: '1',
    locations: ['aaaa', 'bbbbbb', 'cccccc']
  },
  {
    id: '2',
    locations: []
  },
  {
    id: '3',
    locations: ['ddd', 'aaadsad', 'sefd']
  },
  {
    id: '4',
    locations: ['ffff', 'eeee', 'sfdsfsd']
  },
];
const locationIds = results.flatMap(i => i.locations);
console.log(locationIds);
Mamun
  • 66,969
  • 9
  • 47
  • 59
5

You could taka a Array#flatMap with the wanted property. If the property is not given, add a default array || [].

let results = [{ id: '1', locations: ['aaaa', 'bbbbbb', 'cccccc'] }, { id: '2', locations: [] }, { id: '3', locations: ['ddd', 'aaadsad', 'sefd'] }, { id: '4', locations: ['ffff', 'eeee', 'sfdsfsd'] }],
    locationIds = results.flatMap(({ locations }) => locations);

console.log(locationIds);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
3

Can also solve using the Reduce function from Array.prototype.

var newResults = results.reduce(function(acc, curr) {
    return acc.concat(curr.locations)
  },[]
)

hope this helps

paperball
  • 195
  • 1
  • 13
2

I spent too long on this not to post my own solution - interesting puzzle for me, although the other answers are no doubt more performant and readable. It uses the same sort of strategy as your original post, which might help point out where it went wrong.

const locationIds = [].concat
                    .apply([], results.filter(result => 
                    result.locations && result.locations.length > 0)
                    .map(result => { return result.locations }));
lawrence-witt
  • 8,094
  • 3
  • 13
  • 32