Combinar matrices en una matriz después de filtrar

14

Tengo una variedad de objetos, donde solo tomo ubicaciones. Mi objetivo es fusionar estas ubicaciones en una matriz, sin embargo, no lo hago y obtengo una matriz vacía. Así es como lo hago:

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

¿Qué estoy haciendo mal aquí? El resultado debería ser ['aaaa', 'bbbbbb', 'cccccc', 'ddd', 'aaadsad', 'sefd', 'ffff', 'eeee', 'sfdsfsd'];

usuario122222
fuente

Respuestas:

9

No necesitas filteraquí. Simplemente utilice el mapmétodo pasando una función de devolución de llamada que se aplica para cada elemento de la 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
fuente
1
@ user122222, de nada! Puede crear su propia implementación flatMapcomo aquí: stackoverflow.com/questions/39837678/…
Mihai Alexandru-Ionut
7

Puedes probar con flatMap():

El flatMap()método primero mapea cada elemento usando una función de mapeo, luego aplana el resultado en una nueva matriz. Es idéntico a un map()seguido de un flat()de profundidad 1 , pero a flatMap()menudo es bastante útil, ya que fusionar ambos en un método es un poco más 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
fuente
6

Podrías taka a Array#flatMapcon la propiedad deseada. Si no se proporciona la propiedad, agregue una matriz predeterminada || [].

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
fuente
2
Es bueno mencionar que .flatMap no funciona en Edge e IE sin polyfills.
Zydnar
3

También se puede resolver usando la función Reducir de Array.prototype.

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

espero que esto ayude

skyhavoc
fuente
2

Pasé demasiado tiempo en esto para no publicar mi propia solución, un rompecabezas interesante para mí, aunque las otras respuestas son sin duda más efectivas y legibles. Utiliza el mismo tipo de estrategia que su publicación original, lo que podría ayudar a señalar dónde salió mal.

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