Объединить массивы в один массив после фильтрации

14

У меня есть массив объектов, где я беру только массив локаций. Моя цель состоит в том, чтобы объединить эти массивы в один массив, но я не могу этого сделать и получить пустой массив. Вот как я это делаю:

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

что я тут не так делаю? Результат должен быть ['aaaa', 'bbbbbb', 'cccccc', 'ddd', 'aaadsad', 'sefd', 'ffff', 'eeee', 'sfdsfsd'];

user122222
источник

Ответы:

9

Вам не нужно filterздесь. Просто используйте mapметод, передав функцию обратного вызова, которая применяется для каждого элемента в массиве.

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

Михай Александру-Ионут
источник
1
@ user122222, пожалуйста! Вы можете создать свою собственную реализацию, flatMapкак здесь: stackoverflow.com/questions/39837678/…
Михай Александру-Ionut
7

Вы можете попробовать с flatMap():

flatMap()Метод сначала отображает каждый элемент с помощью функции отображения, а затем сглаживает результат в новый массив. Это идентично map()за которым следует flat()из глубины 1 , но flatMap()часто бывает весьма полезно, поскольку слияние обоих в одном из способов является немного более эффективным.

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

Мамун
источник
6

Вы можете взять Array#flatMapс желаемой собственностью. Если свойство не указано, добавьте массив по умолчанию || [].

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

Нина Шольц
источник
2
Хорошо отметить, что .flatMap не работает в Edge и IE без полизаполнений.
Зиднар
3

Можно также решить с помощью функции Reduce из Array.prototype.

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

надеюсь это поможет

skyhavoc
источник
2

Я потратил слишком много времени на то, чтобы не опубликовать собственное решение - интересная головоломка для меня, хотя другие ответы, несомненно, более производительны и читабельны. Он использует ту же стратегию, что и ваш оригинальный пост, что может помочь указать, где это пошло не так.

const locationIds = [].concat
                    .apply([], results.filter(result => 
                    result.locations && result.locations.length > 0)
                    .map(result => { return result.locations }));
Lawrence-Witt
источник