Scal tablice do jednej tablicy po filtrowaniu

14

Mam szereg obiektów, w których biorę tylko tablicę lokalizacji. Moim celem jest połączenie tych tablic lokalizacji w jedną tablicę, jednak nie udało mi się tego i otrzymam pustą tablicę. Tak to robię:

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

co tutaj robię źle? Wynik powinien być ['aaaa', 'bbbbbb', 'cccccc', 'ddd', 'aaadsad', 'sefd', 'ffff', 'eeee', 'sfdsfsd'];

użytkownik122222
źródło

Odpowiedzi:

9

Nie potrzebujesz filtertutaj. Wystarczy użyć mapmetody, przekazując funkcję podaną przez funkcję zwrotną, która jest stosowana dla każdego elementu w tablicy.

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
źródło
1
@ user122222, nie ma za co! Możesz stworzyć własną implementację flatMapjak tutaj: stackoverflow.com/questions/39837678/…
Mihai Alexandru-Ionut
7

Możesz spróbować z flatMap():

flatMap()Sposób pierwszy odwzorowuje każdy element użyciem funkcji odwzorowania, a następnie spłaszcza się wynik do nowej tablicy. To jest identyczne z map(), a następnie przez flat()od głębokości 1 , ale flatMap()jest często bardzo użyteczne, ponieważ połączenie zarówno w jednym ze sposobów jest nieco bardziej efektywny.

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
źródło
6

Możesz mieć taką pożądaną Array#flatMapnieruchomość. Jeśli właściwość nie zostanie podana, dodaj domyślną tablicę || [].

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
źródło
2
Warto wspomnieć, że .flatMap nie działa w Edge i IE bez wielu wypełniaczy.
Zydnar
3

Można również rozwiązać za pomocą funkcji Reduce z Array.prototype.

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

mam nadzieję że to pomoże

skyhavoc
źródło
2

Spędziłem zbyt długo na tym, aby nie publikować własnych rozwiązań - dla mnie interesująca łamigłówka, chociaż pozostałe odpowiedzi są bez wątpienia bardziej wydajne i czytelne. Używa tego samego rodzaju strategii, co oryginalny post, co może pomóc wskazać, gdzie poszło nie tak.

const locationIds = [].concat
                    .apply([], results.filter(result => 
                    result.locations && result.locations.length > 0)
                    .map(result => { return result.locations }));
Lawrence-Witt
źródło