Mesclar matrizes para uma matriz após a filtragem

14

Eu tenho uma matriz de objetos, onde eu levo apenas a matriz de locais. Meu objetivo é mesclar a matriz desses locais em uma matriz, no entanto, falho em fazê-lo e obtém a matriz vazia. É assim que eu faço:

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

o que estou fazendo de errado aqui? O resultado deve ser ['aaaa', 'bbbbbb', 'cccccc', 'ddd', 'aaadsad', 'sefd', 'ffff', 'eeee', 'sfdsfsd'];

user122222
fonte

Respostas:

9

Você não precisa filteraqui. Basta usar o mapmétodo passando uma função fornecida de retorno de chamada que é aplicada a todos os itens da matriz.

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
fonte
11
@ user122222, de nada! Você pode criar sua própria implementação flatMapcomo aqui: stackoverflow.com/questions/39837678/…
Mihai Alexandru-Ionut
7

Você pode tentar com flatMap():

O flatMap()método primeiro mapeia cada elemento usando uma função de mapeamento e depois nivela o resultado em uma nova matriz. É idêntico a um map()seguido por um flat()de profundidade 1 , mas flatMap()geralmente é bastante útil, pois mesclar os dois em um método é um pouco mais eficiente.

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
fonte
6

Você pode levar um Array#flatMapcom a propriedade desejada. Se a propriedade não for fornecida, adicione uma matriz padrão || [].

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
fonte
2
É bom mencionar que o .flatMap não funciona no Edge e no IE sem polyfills.
Zydnar
3

Também pode resolver usando a função Reduzir do Array.prototype.

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

espero que isto ajude

skyhavoc
fonte
2

Gastei muito tempo nisso para não postar minha própria solução - quebra-cabeça interessante para mim, embora as outras respostas sejam sem dúvida mais eficientes e legíveis. Ele usa o mesmo tipo de estratégia da sua postagem original, o que pode ajudar a apontar onde deu errado.

const locationIds = [].concat
                    .apply([], results.filter(result => 
                    result.locations && result.locations.length > 0)
                    .map(result => { return result.locations }));
lawrence-witt
fonte