Mam tablicę obiektów JavaScript o następującej strukturze:
objArray = [ { foo: 1, bar: 2}, { foo: 3, bar: 4}, { foo: 5, bar: 6} ];
Chcę wyodrębnić pole z każdego obiektu i uzyskać tablicę zawierającą wartości, na przykład pole foo
dałoby tablicę [ 1, 3, 5 ]
.
Mogę to zrobić z tym trywialnym podejściem:
function getFields(input, field) {
var output = [];
for (var i=0; i < input.length ; ++i)
output.push(input[i][field]);
return output;
}
var result = getFields(objArray, "foo"); // returns [ 1, 3, 5 ]
Czy istnieje bardziej elegancki lub idiomatyczny sposób, aby to zrobić, aby niestandardowa funkcja narzędzia była niepotrzebna?
Uwaga na temat sugerowanego duplikatu , dotyczy to sposobu konwersji pojedynczego obiektu na tablicę.
var foos = objArray.pluck("foo");
.Array.prototype.map
funkcję tam, gdzie ona istniejeOdpowiedzi:
Oto krótszy sposób na osiągnięcie tego:
LUB
Możesz także sprawdzić
Array.prototype.map()
.źródło
Tak, ale opiera się na funkcji JavaScript JavaScript ES5. Oznacza to, że nie będzie działać w IE8 lub starszej wersji.
W interpretatorach JS kompatybilnych z ES6 możesz użyć funkcji strzałki dla zwięzłości:
Dokumentacja Array.prototype.map
źródło
foo
?var result = objArray.map((a) => (a.foo));
var result = objArray.map(a => a.foo);
Sprawdź funkcję Lodasha
_.pluck()
lub funkcję podkreślenia_.pluck()
. Oba robią dokładnie to, co chcesz w jednym wywołaniu funkcji!Aktualizacja:
_.pluck()
została usunięta od Lodash v4.0.0 , na korzyść_.map()
w połączeniu z czymś podobnym do odpowiedzi Nieta ._.pluck()
jest nadal dostępny w podkreśleniu .Aktualizacja 2: Jak Mark wskazuje w komentarzach , gdzieś pomiędzy Lodash v4 a 4.3, dodano nową funkcję, która zapewnia tę funkcjonalność ponownie.
_.property()
jest stenograficzną funkcją, która zwraca funkcję do pobierania wartości właściwości w obiekcie.Dodatkowo
_.map()
umożliwia teraz przekazanie ciągu jako drugiego parametru, do którego jest przekazywany_.property()
. W rezultacie następujące dwa wiersze są równoważne powyższemu przykładowi kodu z wersji sprzed Lodash 4._.property()
, a zatem_.map()
pozwalają również podać ciąg lub tablicę oddzieloną kropkami, aby uzyskać dostęp do właściwości podrzędnych:Oba
_.map()
połączenia w powyższym przykładzie zostaną zwrócone[5, 2, 9]
.Jeśli bardziej interesujesz się programowaniem funkcjonalnym, spójrz na funkcję Ramdy
R.pluck()
, która wyglądałaby mniej więcej tak:źródło
_.property('foo')
( lodash.com/docs#property ) dodano jako skrótfunction(o) { return o.foo; }
. Skraca to przypadek użycia Lodash.var result = _.pluck(objArray, _.property('foo'));
Dla większej wygody_.map()
metoda Lodash 4.3.0 pozwala również na stosowanie skrótu_.property()
pod maską, w wyniku czegovar result = _.map(objArray, 'foo');
Mówiąc o rozwiązaniach tylko dla JS, odkryłem, że choć nieelegancka, prosta
for
pętla indeksowana jest bardziej wydajna niż jej alternatywy.Wyodrębnianie pojedynczej właściwości z tablicy elementów 100000 (przez jsPerf)
Tradycyjny dla pętli 368 operacji / sek
ES6 dla ... pętli 303 operacji / s
Array.prototype.map 19 operacji / s
TL; DR - .map () jest wolny, ale możesz go używać, jeśli uważasz, że czytelność jest warta więcej niż wydajność.
Edytuj # 2: 6/2019 - Uszkodzony, usunięty link jsPerf.
źródło
Używanie
Array.prototype.map
:Zobacz powyższy link, aby uzyskać podkładkę dla przeglądarek wcześniejszych niż ES5.
źródło
Lepiej jest użyć pewnego rodzaju bibliotek, takich jak lodash lub podkreślnik, dla zapewnienia bezpieczeństwa w różnych przeglądarkach.
W Lodash można uzyskać wartości właściwości w tablicy, wykonując następującą metodę
oraz w podkreśleniu
Oba powrócą
źródło
W ES6 możesz:
źródło
Chociaż
map
jest właściwym rozwiązaniem do wybierania „kolumn” z listy obiektów, ma jednak pewną wadę. Jeśli nie zostanie wyraźnie zaznaczone, czy kolumny istnieją, wygeneruje błąd i (co najwyżej) zapewniundefined
. Wybrałbymreduce
rozwiązanie, które może po prostu zignorować właściwość lub nawet ustawić dla ciebie wartość domyślną.przykład jsbin
Działa to nawet wtedy, gdy jeden z elementów na podanej liście nie jest obiektem lub nie zawiera pola.
Można go nawet uelastycznić, negocjując wartość domyślną, jeśli element nie jest obiektem lub nie zawiera pola.
przykład jsbin
Tak samo byłoby z mapą, ponieważ długość zwróconej tablicy byłaby taka sama jak dostarczonej tablicy. (W takim przypadku a
map
jest nieco tańsze niż areduce
):przykład jsbin
A potem jest najbardziej elastyczne rozwiązanie, które pozwala przełączać się między oboma zachowaniami, po prostu zapewniając alternatywną wartość.
przykład jsbin
Ponieważ powyższe przykłady (mam nadzieję) rzuciły nieco światła na sposób, w jaki to działa, pozwólmy nieco skrócić tę funkcję, korzystając z tej
Array.concat
funkcji.przykład jsbin
źródło
Ogólnie rzecz biorąc, jeśli chcesz ekstrapolować wartości obiektów znajdujące się w tablicy (jak opisano w pytaniu), możesz użyć funkcji redukcji, mapowania i destrukcji tablicy.
ES6
Odpowiednikiem użycia pętli for byłoby:
Wyprodukowano: [„słowo”, „ponownie”, „niektóre”, „1”, „2”, „3”]
źródło
To zależy od twojej definicji „lepszego”.
Inne odpowiedzi wskazują na użycie mapy, która jest naturalna (szczególnie dla facetów przyzwyczajonych do funkcjonalnego stylu) i zwięzła. Zdecydowanie polecam go używać (jeśli nie przeszkadza ci kilku facetów IE8-IT). Więc jeśli „lepszy” oznacza „bardziej zwięzły”, „łatwy do utrzymania”, „zrozumiały”, to tak, jest o wiele lepszy.
Z drugiej strony to piękno nie przychodzi bez dodatkowych kosztów. Nie jestem wielkim fanem mikrobenchów, ale tutaj przeprowadziłem mały test . Rezultaty są przewidywalne, stary brzydki sposób wydaje się być szybszy niż funkcja mapy. Więc jeśli „lepszy” oznacza „szybszy”, to nie, pozostań przy modzie starej szkoły.
Znowu jest to tylko mikrobench i w żaden sposób nie odradzam używania
map
, to tylko moje dwa centy :).źródło
map
to obiwna droga, jakoś nie udało mi się znaleźć google (znalazłem tylko mapę jquery, co nie jest istotne).Jeśli chcesz również obsługiwać obiekty podobne do tablic, użyj Array.from (ES2015):
Przewagą nad metodą Array.prototype.map () jest to, że dane wejściowe mogą być również zestawem :
źródło
Jeśli chcesz mieć wiele wartości w ES6 +, następujące będą działać
Działa to tak, jak
{foo, baz}
po lewej stronie jest niszczenie obiektów, a po prawej stronie strzałki jest równoważne ze{foo: foo, baz: baz}
względu na ulepszone literały obiektów ES6 .źródło
Mapa funkcji jest dobrym wyborem w przypadku tablic obiektów. Chociaż opublikowano już wiele dobrych odpowiedzi, pomocne może być użycie mapy w połączeniu z filtrem.
Jeśli chcesz wykluczyć właściwości, których wartości są niezdefiniowane lub wykluczyć tylko określoną właściwość, możesz wykonać następujące czynności:
https://jsfiddle.net/ohea7mgk/
źródło
Powyższa odpowiedź jest dobra do wyodrębnienia pojedynczej właściwości, co jeśli chcesz wyodrębnić więcej niż jedną właściwość z tablicy obiektów. Oto rozwiązanie !! W takim przypadku możemy po prostu użyć _.pick (obiekt, [ścieżki])
Załóżmy, że obiekt objArray ma obiekty o trzech właściwościach, takich jak poniżej
Teraz chcemy wyodrębnić właściwości foo i bar z każdego obiektu i przechowywać je w osobnej tablicy. Najpierw wykonamy iterację elementów tablicy za pomocą mapy, a następnie zastosujemy na niej metodę Lodash Library Standard _.pick ().
Teraz możemy wyodrębnić właściwość „foo” i „bar”.
var newArray = objArray.map((element)=>{ return _.pick(element, ['foo','bar'])}) console.log(newArray);
a wynikiem byłoby [{foo: 1, takt: 2}, {foo: 3, takt: 4}, {foo: 5, takt: 6}]
cieszyć się!!!
źródło
_.pick
pochodzi? To nie jest standardowa funkcja.Jeśli masz zagnieżdżone tablice, możesz sprawić, aby działało w następujący sposób:
źródło