Mam tablicę:
[1, 2, 3, 5, 2, 8, 9, 2]
Chciałbym wiedzieć, ile 2
s znajduje się w tablicy.
Jaki jest najbardziej elegancki sposób zrobienia tego w JavaScript bez zapętlenia z for
pętlą?
javascript
Leem
źródło
źródło
const count = countItems(array, 2);
a szczegóły implementacji można dyskutować wewnątrz.[ ta odpowiedź jest nieco przestarzała: przeczytaj zmiany ]
Przywitaj się ze znajomymi:
map
ifilter
ireduce
iforEach
ievery
itd.(Tylko sporadycznie piszę pętle for w javascript, ponieważ brakuje zakresu na poziomie bloku, więc i tak musisz użyć funkcji jako ciała pętli, jeśli chcesz przechwycić lub sklonować indeks lub wartość iteracji. generalnie są bardziej wydajne, ale czasami potrzebujesz zamknięcia).
Najbardziej czytelny sposób:
(
.filter(function(x){return x==2}).length
Zamiast tego moglibyśmy napisać )Poniższe dane są bardziej wydajne przestrzennie (O (1) zamiast O (N)), ale nie jestem pewien, ile korzyści / kary możesz zapłacić pod względem czasu (nie więcej niż stały współczynnik od czasu wizyty każdy element dokładnie raz):
(Jeśli chcesz zoptymalizować ten konkretny fragment kodu, pętla for może być szybsza w niektórych przeglądarkach ... możesz przetestować rzeczy na jsperf.com).
Możesz wtedy być elegancki i przekształcić go w funkcję prototypową:
Lubię to:
Możesz również umieścić zwykłą starą technikę pętli for (zobacz inne odpowiedzi) wewnątrz powyższej definicji właściwości (znowu, prawdopodobnie będzie to znacznie szybsze).
Edycja 2017 :
Ups, ta odpowiedź stała się bardziej popularna niż poprawna odpowiedź. Właściwie po prostu użyj zaakceptowanej odpowiedzi. Chociaż ta odpowiedź może być urocza, kompilatory js prawdopodobnie nie (lub nie mogą z powodu specyfikacji) optymalizować takich przypadków. Więc naprawdę powinieneś napisać prostą pętlę for:
Możesz zdefiniować wersję, w
.countStrictEq(...)
której używane jest===
pojęcie równości. Pojęcie równości może być ważne dla tego, co robisz! (na przykład[1,10,3,'10'].count(10)==2
, ponieważ liczby takie jak „4” == 4 w javascript ... dlatego wywołując je.countEq
lub.countNonstrict
podkreślają, że używa==
operatora).Rozważ także użycie własnej wielozbiorowej struktury danych (np. Jak w Pythonie '
collections.Counter
'), aby uniknąć konieczności liczenia w pierwszej kolejności.Próbny:
sidenote: Chociaż, jeśli nadal chcesz funkcjonalnego sposobu programowania (lub jednorazowego, jednowierszowego tekstu bez nadpisywania Array.prototype), możesz dziś napisać to bardziej zwięźle jako
[...].filter(x => x==2).length
. Jeśli zależy Ci na wydajności, pamiętaj, że chociaż jest to asymptotycznie taka sama wydajność jak pętla for (czas O (N)), może wymagać dodatkowej pamięci O (N) (zamiast pamięci O (1)), ponieważ będzie to prawie z pewnością wygeneruj tablicę pośrednią, a następnie policz elementy tej tablicy pośredniej.źródło
array.reduce(function(total,x){return x==value? : total+1 : total}, 0)
[...].reduce(function(total,x){return x==2 ? total+1 : total}, 0)
const count = (list) => list.filter((x) => x == 2).length
. Następnie użyj go, dzwoniąc,count(list)
gdzie lista jest tablicą liczb. Możesz takżeconst count = (list) => list.filter((x) => x.someProp === 'crazyValue').length
policzyć wystąpienia crazyValue w tablicy obiektów. Uwaga, jest to dokładne dopasowanie do właściwości.Aktualizacja ES6 do JS:
Pamiętaj, że zawsze powinieneś używać potrójnych równości:
===
aby uzyskać prawidłowe porównanie:Następująca jednomyślna funkcja Arrow (funkcja lambda) w JS:
można uprościć do tego zwięzłego formularza dla pojedynczego wejścia:
gdzie
return
jest domniemane.źródło
2017: Jeśli ktoś nadal jest zainteresowany pytaniem, moje rozwiązanie jest następujące:
źródło
Jeśli używasz lodash lub podkreślenia, metoda _.countBy zapewni obiekt zagregowanych sum wpisanych przez każdą wartość w tablicy. Możesz zmienić to w jednolinijkowy, jeśli chcesz policzyć tylko jedną wartość:
Działa to również dobrze w przypadku tablic liczb. Jednowierszowy przykład będzie wyglądał następująco:
źródło
Najdziwniejszy sposób, w jaki mogę to zrobić, to:
Gdzie:
Moja sugestia, wykorzystaj chwilę lub pętlę ;-)
źródło
Brak pętli oznacza zwykle przekazanie procesu do jakiejś metody, która korzysta z pętli.
Oto sposób, w jaki nasz programista, który nienawidzi pętli, może zaspokoić swoją nienawiść za pewną cenę:
Możesz również wielokrotnie wywoływać indexOf, jeśli jest dostępna jako metoda tablicowa, i za każdym razem przesuwać wskaźnik wyszukiwania.
Nie tworzy to nowej tablicy, a pętla jest szybsza niż forEach lub filter.
Jeśli masz milion członków, na których możesz spojrzeć, może to mieć znaczenie.
źródło
String(a).match(/2/g).length + 1
- chociaż uważaj na to, bo inaczej Twoja implementacja nie będzie dobrze działać z dwucyfrowymi liczbami.Większość opublikowanych rozwiązań wykorzystujących funkcje tablicowe, takie jak filtr, jest niekompletna, ponieważ nie są sparametryzowane.
Oto rozwiązanie, za pomocą którego element do zliczania można ustawić w czasie wykonywania.
Zaletą tego podejścia jest to, że można łatwo zmienić funkcję, aby policzyć na przykład liczbę elementów większą niż X.
Możesz również zadeklarować funkcję redukcji w tekście
źródło
var elementToFind=2; ... function (elementToFind, total, number){ return total += number==elementToFind; }.bind(this, elementToFind) ...
jest trudniejszy do odczytania i nie daje żadnej przewagi nad sprawiedliwymi... (acc, x) => acc += number == 2...
. Podoba mi się, że używasz+=
zamiastacc + (number == 2)
tego. Czuje się jednak jak nieuzasadnione hakowanie składni.Naprawdę, dlaczego trzeba
map
albofilter
do tego?reduce
„urodził się” dla tego rodzaju operacji:[1, 2, 3, 5, 2, 8, 9, 2].reduce( (count,2)=>count+(item==val), 0);
Otóż to! (jeśli
item==val
w każdej iteracji, to 1 zostanie dodany do akumulatoracount
, zgodnietrue
z rozwiązaniem1
).Jako funkcja:
Lub śmiało rozszerz swoje tablice:
źródło
Lepiej jest opakować go w funkcję:
źródło
Oto sposób ES2017 +, aby uzyskać zliczenia dla wszystkich elementów tablicy w O (N):
Możesz również opcjonalnie posortować dane wyjściowe:
console.log (countsSorted) dla Twojej przykładowej tablicy:
źródło
Wierzę, że szukasz funkcjonalnego podejścia
elem === „a” to warunek, zastąp go własnym.
źródło
count = arr.filter(elem => elem === 'a').length
lubcount = arr.filter(elem => {return elem === 'a'}).length
Jestem początkującym fanem funkcji redukującej js array.
W rzeczywistości, jeśli naprawdę chcesz się spodobać, możesz utworzyć funkcję zliczającą w prototypie Array. Następnie możesz go użyć ponownie.
Więc zrób
źródło
Rozwiązanie przez rekurencję
źródło
filter
,reduce
lub prostyforLoop
, a także droższe patrząc na wydajność, ale nadal świetny sposób to zrobić z rekursji. Moją jedyną zmianą jest: po prostu myślę, że byłoby lepiej utworzyć funkcję i dodać do niej filtr, aby skopiować tablicę i uniknąć mutacji oryginalnej tablicy, a następnie użyć funkcji rekurencyjnej jako funkcji wewnętrznej.Zrobiłbym coś takiego:
źródło
Utwórz nową metodę dla klasy Array w pliku poziomu podstawowego i używaj jej w całym projekcie.
Użyj tego w dowolnym miejscu w swoim projekcie -
źródło
Oto jedna linijka w javascript.
(v === 2)
w tablicy, zwracając tablicę jedynek i zer.Wynik jest
3
.źródło
W zależności od tego, jak chcesz go uruchomić:
źródło
Możesz użyć właściwości length w tablicy JavaScript:
źródło