Próbuję użyć nowego obiektu Map z Javascript EC6, ponieważ jest już obsługiwany w najnowszych wersjach przeglądarki Firefox i Chrome.
Ale uważam, że jest to bardzo ograniczone w programowaniu "funkcjonalnym", ponieważ brakuje w nim klasycznych metod mapowania, filtrów itp., Które dobrze działałyby z [key, value]
parą. Ma forEach, ale to NIE zwraca wyniku wywołania zwrotnego.
Gdybym mógł przekształcić go map.entries()
z MapIteratora w prostą tablicę, mógłbym użyć standardu.map
, .filter
bez dodatkowych hacków.
Czy istnieje „dobry” sposób na przekształcenie Iteratora JavaScript w tablicę? W Pythonie jest to tak proste, jak zrobienie list(iterator)
... ale Array(m.entries())
zwróć tablicę z Iteratorem jako pierwszym elementem !!!
EDYTOWAĆ
Zapomniałem sprecyzować, że szukam odpowiedzi, która działa wszędzie tam, gdzie działa Mapa, czyli przynajmniej Chrome i Firefox (Array.from nie działa w Chrome).
PS.
Wiem, że istnieje fantastyczny wu.js, ale jego zależność od traceur mnie zniechęca ...
źródło
Odpowiedzi:
Szukasz nowej
Array.from
funkcji, która konwertuje dowolne iterable na instancje tablic:Jest teraz obsługiwany w Edge, FF, Chrome i Node 4+ .
Oczywiście, być może warto zdefiniować
map
,filter
i podobne metody bezpośrednio na interfejsie iteracyjnej, dzięki czemu można uniknąć alokacji tablicy. Możesz także użyć funkcji generatora zamiast funkcji wyższego rzędu:źródło
(value, key)
pary, a nie(value, index)
pary.yourTransformation = function([key, value], index) { … }
Map
ma pary klucz-wartość. Stąd, moim skromnym zdaniem, nie ma sensu definiowanie generałamap
ifilter
funkcji dla iteratorów. Zamiast tego każdy iterowalny obiekt powinien mieć swoje własne funkcjemap
ifilter
funkcje. Ma to sens, ponieważ operacje zachowujące strukturęmap
ifilter
są operacjami zachowującymi strukturę (być może nie,filter
ale namap
pewno tak jest), a zatem funkcjemap
ifilter
powinny znać strukturę iterowalnych obiektów, nad którymi mapują lub filtrują. Pomyśl o tym, w Haskell definiujemy różne przypadkiFunctor
. =)[...map.entries()]
lubArray.from(map.entries())
To bardzo łatwe.
W każdym razie - w iteratorach brakuje metody redukującej, filtrującej i podobnych. Musisz napisać je samodzielnie, ponieważ jest to bardziej wydajne niż konwersja Map na tablicę iz powrotem. Ale nie rób skoków Mapa -> Array -> Map -> Array -> Map -> Array, ponieważ to zabije wydajność.
źródło
Array.from
został już objęty @Bergi.[iterator]
nie działa, ponieważ w Chrome tworzy tablicę z jednymiterator
elementem, a[...map.entries()]
nie jest akceptowaną składnią w ChromeNie ma potrzeby przekształcania pliku
Map
wArray
. Możesz po prostu utworzyćmap
ifilter
funkcjonować dlaMap
obiektów:Na przykład, możesz dołączyć huk (tj.
!
Znak) do wartości każdego wpisu mapy, której klucz jest prymitywem.Możesz także dodać
map
ifilter
metody,Map.prototype
aby lepiej czytać. Chociaż generalnie nie zaleca się modyfikowania natywnych prototypów, uważam, że można zrobić wyjątek w przypadkumap
ifilter
dlaMap.prototype
:Edycja: w odpowiedzi Bergi stworzył ogólne
map
ifilter
funkcje generujące dla wszystkich iterowalnych obiektów. Zaletą ich używania jest to, że ponieważ są to funkcje generujące, nie przydzielają pośrednich iterowalnych obiektów.Na przykład funkcje my
map
ifilter
zdefiniowane powyżej tworzą noweMap
obiekty. Stąd wywołanieobject.filter(primitive).map(appendBang)
tworzy dwa noweMap
obiekty:Tworzenie pośrednich obiektów iterowalnych jest kosztowne. Funkcje generatora Bergiego rozwiązują ten problem. Nie alokują obiektów pośrednich, ale pozwalają jednemu iteratorowi na leniwe przekazywanie swoich wartości do następnego. Ten rodzaj optymalizacji jest znany jako fuzja lub wylesianie w funkcjonalnych językach programowania i może znacznie poprawić wydajność programu.
Jedyny problem, jaki mam z funkcjami generatora Bergi, polega na tym, że nie są one specyficzne dla
Map
obiektów. Zamiast tego są uogólnione dla wszystkich iterowalnych obiektów. Dlatego zamiast wywoływać funkcje zwrotne z(value, key)
parami (jak spodziewałbym się przy mapowaniu na aMap
), wywołuje funkcje zwrotne z(value, index)
parami. W przeciwnym razie jest to doskonałe rozwiązanie i zdecydowanie polecam używanie go zamiast rozwiązań, które dostarczyłem.Oto konkretne funkcje generatora, których użyłbym do mapowania i filtrowania
Map
obiektów:Można ich używać w następujący sposób:
Jeśli chcesz mieć bardziej płynny interfejs, możesz zrobić coś takiego:
Mam nadzieję, że to pomoże.
źródło
Map
obiektów przy użyciu wyspecjalizowanychmap
ifilter
funkcji. Odpowiedź Bergiego demonstruje użycie typów ogólnychmap
ifilter
funkcji dla wszystkich obiektów iterowalnych, których nie można użyć do przekształcaniaMap
obiektów, ponieważ kluczeMap
obiektu zostały utracone.Array.from
nie działa w Chrome (podczas gdy mapa i iteratory tak!). Ale widzę, że podejście jest bardzo podobne i możesz po prostu dodać funkcję „toArray” do swojej grupy!toArray
funkcję.Mała aktualizacja z 2019 roku:
Teraz Array.from wydaje się być powszechnie dostępny, a ponadto przyjmuje drugi argument mapFn , który uniemożliwia mu utworzenie pośredniej tablicy. Zasadniczo wygląda to tak:
źródło
Array.from
już istnieje, bardziej nadaje się jako komentarz lub żądana edycja tej odpowiedzi ... ale dzięki!Możesz użyć biblioteki, takiej jak https://www.npmjs.com/package/itiriri, która implementuje metody podobne do tablic dla iterable:
źródło
Możesz uzyskać tablicę tablic (klucz i wartość):
Następnie możesz łatwo uzyskać wartości od wewnątrz, na przykład klucze z iteratorem mapy.
źródło
Możesz również użyć płynnej iteracji, aby przekształcić w tablicę:
źródło