Jaki jest najbardziej zwięzły i wydajny sposób sprawdzenia, czy tablica JavaScript zawiera wartość?
To jedyny znany mi sposób:
function contains(a, obj) {
for (var i = 0; i < a.length; i++) {
if (a[i] === obj) {
return true;
}
}
return false;
}
Czy istnieje lepszy i bardziej zwięzły sposób na osiągnięcie tego?
Jest to bardzo ściśle związane z pytaniem Przepełnienie stosu Najlepszy sposób na znalezienie elementu w tablicy JavaScript? który adresuje wyszukiwanie obiektów w tablicy za pomocą indexOf
.
~[1,2,3].indexOf(4)
zwróci 0, które zostanie ocenione jako fałsz, podczas gdy~[1,2,3].indexOf(3)
zwróci -3, które oceni jako prawdę.~
nie jest tym, czego chcesz użyć do konwersji na wartość logiczną, do tego potrzebujesz!
. Ale w tym przypadku chcesz sprawdzić równość z -1, więc funkcja może się skończyć, niereturn [1,2,3].indexOf(3) === -1;
~
jest binarna, odwróci każdy bit wartości osobno.[1,2,3].indexOf(4)
faktycznie zwróci -1 . Jak wskazał @mcfedr,~
jest operatorem bitowym NIE , patrz ES5 11.4.8. Chodzi o to, że ponieważ binarna reprezentacja-1
składa się tylko z 1, dopełnieniem jest0
, co jest oceniane jako fałsz. Uzupełnienie dowolnej innej liczby będzie niezerowe, a zatem prawdziwe. Więc~
działa dobrze i jest często używany w połączeniu zindexOf
.[[1,2],[3,4]].includes([3,4])
?Odpowiedzi:
Nowoczesne przeglądarki mają to
Array#includes
, co robi dokładnie to i jest szeroko obsługiwane przez wszystkich oprócz IE:Możesz także użyć
Array#indexOf
, który jest mniej bezpośredni, ale nie wymaga wypełniania wielopełniaczy w przypadku przestarzałych przeglądarek.Wiele platform oferuje również podobne metody:
$.inArray(value, array, [fromIndex])
_.contains(array, value)
(również aliasy jako_.include
i_.includes
)dojo.indexOf(array, value, [fromIndex, findLast])
array.indexOf(value)
array.indexOf(value)
findValue(array, value)
array.indexOf(value)
Ext.Array.contains(array, value)
_.includes(array, value, [from])
(_.contains
wcześniejszy niż 4.0.0)R.includes(value, array)
Zauważ, że niektóre frameworki implementują to jako funkcję, podczas gdy inne dodają tę funkcję do prototypu tablicy.
źródło
Array.include
funkcję zwracającą wartość logicznąarray.indexOf(object) != -1
inArray
to okropna nazwa dla funkcji, która zwraca indeks elementu, a-1
jeśli nie istnieje. Spodziewałbym się zwrotu wartości logicznej.Aktualizacja z 2019 r .: Ta odpowiedź pochodzi z 2008 r. (11 lat!) I nie ma zastosowania w nowoczesnym użyciu JS. Obiecana poprawa wydajności została oparta na teście porównawczym przeprowadzonym w przeglądarkach tego czasu. Może to nie być istotne w kontekście współczesnego wykonywania JS. Jeśli potrzebujesz łatwego rozwiązania, poszukaj innych odpowiedzi. Jeśli potrzebujesz najlepszej wydajności, sprawdź swoje standardy w odpowiednich środowiskach wykonawczych.
Jak powiedzieli inni, iteracja przez tablicę jest prawdopodobnie najlepszym sposobem, ale udowodniono, że malejąca
while
pętla jest najszybszym sposobem na iterację w JavaScript. Możesz więc przepisać kod w następujący sposób:Oczywiście możesz równie dobrze rozszerzyć prototyp Array:
A teraz możesz po prostu użyć następujących opcji:
źródło
for (o in array)
indexOf
może, ale jest to „rozszerzenie JavaScript do standardu ECMA-262; jako takie może nie być obecne w innych implementacjach tego standardu”.Przykład:
AFAICS Microsoft nie oferuje żadnej alternatywy dla tego, ale możesz dodać podobną funkcjonalność do tablic w Internet Explorerze (i innych przeglądarkach, które nie obsługują
indexOf
), jeśli chcesz, jak ujawnia szybkie wyszukiwanie Google (na przykład ta ).źródło
ECMAScript 7 wprowadza
Array.prototype.includes
.Można go użyć w następujący sposób:
Akceptuje również opcjonalny drugi argument
fromIndex
:W przeciwieństwie do tego
indexOf
, który korzysta ze ścisłego porównania równości ,includes
porównuje za pomocą algorytmu równości SameValueZero . Oznacza to, że możesz wykryć, czy tablica zawieraNaN
:Również w przeciwieństwie
indexOf
,includes
nie pominąć brakujące indeksy:Obecnie jest to wersja robocza, ale można ją wypełnić, aby działała na wszystkich przeglądarkach.
źródło
Najważniejsze odpowiedzi zakładają prymitywne typy, ale jeśli chcesz dowiedzieć się, czy tablica zawiera obiekt z jakąś cechą, Array.prototype.some () jest bardzo eleganckim rozwiązaniem:
Zaletą jest to, że iteracja jest przerywana po znalezieniu elementu, dzięki czemu oszczędza się niepotrzebnych cykli iteracji.
Ponadto dobrze pasuje do
if
instrukcji, ponieważ zwraca wartość logiczną:* Jak wskazał jamess w komentarzu, w momencie udzielania odpowiedzi, wrzesień 2018 r.,
Array.prototype.some()
Jest w pełni obsługiwany: tabela wsparcia caniuse.comźródło
Arrow functions
w tym przykładzie nie są tak dobrze obsługiwane. Aby uzyskać więcej informacji, zobacz tutaj: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Powiedzmy, że zdefiniowałeś tablicę tak:
Poniżej znajdują się trzy sposoby sprawdzenia, czy tam jest
3
. Wszystkie z nich powrócić albotrue
albofalse
.Metoda Native Array (od ES2016) ( tabela kompatybilności )
Jako niestandardowa metoda macierzy (sprzed ES2016)
Prosta funkcja
źródło
Oto implementacja kompatybilna z JavaScript 1.6
Array.indexOf
:źródło
[].indexOf
jest skrótem odArray.prototype.indexOf
. My, programiści w obronie przed paranoidami Javascript, unikają za wszelką cenę rozszerzania natywnych prototypów.[].indexOf
tworzy nowej tablicy, a następnie uzyskuje do niej dostępindexOf
,Array.prototype.indexOf
po prostu uzyskuje bezpośredni dostęp do prototypu?[].indexOf === Array.prototype.indexOf
(wypróbuj w FireBug), ale odwrotnie[].indexOf !== Array.indexOf
.Posługiwać się:
źródło
x ? true : false
jest zwykle zbędny. To jest tutaj.array.indexOf(search) >= 0
jest już wartością logiczną. Właśniereturn array.indexOf(search) >= 0
.Rozszerzanie
Array
obiektu JavaScript jest naprawdę złym pomysłem, ponieważ wprowadzasz nowe właściwości (własne metody) dofor-in
pętli, które mogą uszkodzić istniejące skrypty. Kilka lat temu autorzy biblioteki Prototype musieli przeprojektować swoją implementację biblioteki, aby usunąć właśnie tego rodzaju rzeczy.Jeśli nie musisz się martwić o kompatybilność z innymi skryptami JavaScript działającymi na twojej stronie, skorzystaj z niej, w przeciwnym razie poleciłbym bardziej niezręczne, ale bezpieczniejsze rozwiązanie funkcji wolnostojącej.
źródło
Jednowarstwowy:
źródło
array.filter(e=>e==x).length > 0
jest równoważne,array.some(e=>e==x)
alesome
jest bardziej wydajneMyśląc od razu po wyjęciu z pudełka, jeśli wykonujesz to połączenie wiele razy, o wiele bardziej efektywne jest użycie
tablicy asocjacyjnejmapy do wyszukiwania za pomocą funkcji skrótu.https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
źródło
Używam następujących:
źródło
Array.prototype.some () został dodany do standardu ECMA-262 w 5. edycji
źródło
contains = (a, obj) => a.some((element) => element === obj))
Mam nadzieję, że szybsza dwukierunkowa
indexOf
/lastIndexOf
alternatywna2015 r
Podczas gdy nowa metoda obejmuje jest bardzo przyjemna, wsparcie jest w zasadzie zerowe na razie.
Już dawno myślałem o sposobie zastąpienia powolnych funkcji indexOf / lastIndexOf.
Znaleźliśmy już skuteczny sposób, patrząc na najlepsze odpowiedzi. Z tych wybrałem
contains
funkcję opublikowaną przez @Damir Zekic, która powinna być najszybsza. Ale stwierdza również, że poziomy odniesienia pochodzą z 2008 r., A więc są nieaktualne.Ja też wolę
while
sięfor
, ale nie konkretnego powodu skończyło pisanie funkcji z pętli for. Można to również zrobić za pomocąwhile --
.Byłem ciekawy, czy iteracja jest znacznie wolniejsza, jeśli sprawdzę obie strony tablicy podczas jej wykonywania. Najwyraźniej nie, a więc ta funkcja jest około dwa razy szybsza niż te najczęściej wybierane. Oczywiście jest także szybszy niż rodzimy. To w prawdziwym świecie, w którym nigdy nie wiadomo, czy szukana wartość znajduje się na początku, czy na końcu tablicy.
Kiedy wiesz, że właśnie wypchnąłeś tablicę z wartością, użycie lastIndexOf pozostaje prawdopodobnie najlepszym rozwiązaniem, ale jeśli musisz podróżować przez duże tablice, a wynik może być wszędzie, może to być solidne rozwiązanie, aby przyspieszyć.
Dwukierunkowy indexOf / lastIndexOf
Test wydajności
http://jsperf.com/bidirectionalindexof
Jako test stworzyłem tablicę zawierającą 100 000 wpisów.
Trzy zapytania: na początku, w środku i na końcu tablicy.
Mam nadzieję, że to również Cię zainteresuje i przetestujesz wydajność.
Uwaga: Jak widać nieznacznie zmodyfikowałem
contains
funkcję, aby odzwierciedlić dane wyjściowe indexOf i lastIndexOf (tak w zasadzietrue
za pomocąindex
i zafalse
pomocą-1
). To nie powinno tego zaszkodzić.Wariant prototypowy tablicy
Funkcję można również łatwo zmodyfikować, aby zwracała wartość prawda lub fałsz, a nawet obiekt, ciąg znaków lub cokolwiek to jest.
A oto
while
wariant:Jak to jest możliwe?
Myślę, że proste obliczenia, aby uzyskać indeks odbity w tablicy, są tak proste, że są dwa razy szybsze niż wykonanie iteracji pętli.
Oto złożony przykład wykonywania trzech kontroli na iterację, ale jest to możliwe tylko przy dłuższych obliczeniach, które powodują spowolnienie kodu.
http://jsperf.com/bidirectionalindexof/2
źródło
Wydajność
Dzisiaj 2020.01.07 Przeprowadzam testy na MacOs HighSierra 10.13.6 na Chrome v78.0.0, Safari v13.0.4 i Firefox v71.0.0 dla 15 wybranych rozwiązań. Wnioski
JSON
,Set
i zaskakującofind
(K, N, O) są najwolniej wszystkich przeglądarekincludes
(F) jest szybki tylko na chromiefor
(C, D) iindexOf
(G, H) są dość szybkie we wszystkich przeglądarkach na małych i dużych tablicach, więc prawdopodobnie są najlepszym wyborem dla wydajnego rozwiązaniafor
(C, D, E) dają podobne wyniki (~ 630 operacji / s - ale E na safari i firefoxie wynosiło 10- 20% wolniej niż C i D)Wyniki
Detale
Wykonuję 2 przypadki testowe: dla tablicy z 10 elementami i tablicy z 1 milionem elementów. W obu przypadkach umieszczamy szukany element w środku tablicy.
Pokaż fragment kodu
Tablica mała - 10 elementów
Testy możesz wykonać na swoim urządzeniu TUTAJ
Tablica duża - 1.000.000 elementów
Testy możesz wykonać na swoim urządzeniu TUTAJ
źródło
Jeśli używasz JavaScript 1.6 lub nowszy (Firefox 1.5 lub nowszy), możesz użyć Array.indexOf . W przeciwnym razie myślę, że skończysz z czymś podobnym do oryginalnego kodu.
źródło
Zwraca indeks tablicy, jeśli został znaleziony, lub -1, jeśli nie został znaleziony
źródło
Używamy tego fragmentu kodu (działa z obiektami, tablicami, ciągami znaków):
Stosowanie:
źródło
Jeśli wielokrotnie sprawdzasz, czy istnieje obiekt w tablicy, powinieneś się przyjrzeć
contains(a, obj)
.źródło
Rozwiązanie, które działa we wszystkich nowoczesnych przeglądarkach:
Stosowanie:
Rozwiązanie IE6 +:
Stosowanie:
Dlaczego warto skorzystać
JSON.stringify
?Array.indexOf
orazArray.includes
(podobnie jak większość odpowiedzi tutaj) porównuj tylko przez odniesienie, a nie według wartości.Premia
Niezoptymalizowany jednowarstwowy ES6:
Uwaga: Porównywanie obiektów pod względem wartości będzie działać lepiej, jeśli klucze są w tej samej kolejności, więc dla bezpieczeństwa możesz najpierw posortować klucze za pomocą pakietu takiego jak ten: https://www.npmjs.com/package/sort-keys
Zaktualizowano
contains
funkcję o optymalizację perf. Dzięki itinance za wskazanie tego.źródło
includes
funkcję o twoją sugestię. Uruchomiłem jsperf z moją funkcją. Jest około 5 razy wolniejszy niż lodysz. Choć lodash nie można porównać pod względem wartości i nie można znaleźć{a: 1}
w[{a: 1}]
. Nie wiem, czy robi to jakaś biblioteka. Ale jestem ciekawy, czy istnieje jakiś bardziej wydajny i niezbyt skomplikowany sposób.contains([{ a: 1, b: 2 }], { b: 2, a: 1 })
ponieważ obiekty strunowe zachowują kolejność właściwości.sort-keys
notatkę na doleUżyj jakiejś funkcji lodash .
Jest zwięzły, dokładny i ma doskonałą obsługę wielu platform.
Akceptowana odpowiedź nawet nie spełnia wymagań.
Wymagania: Poleć najbardziej zwięzły i skuteczny sposób sprawdzenia, czy tablica JavaScript zawiera obiekt.
Zaakceptowana odpowiedź:
Moja rekomendacja:
Uwagi:
$ .inArray działa dobrze w celu ustalenia, czy istnieje wartość skalarna w tablicy skalarów ...
... ale pytanie wyraźnie wymaga skutecznego sposobu ustalenia, czy obiekt jest zawarty w tablicy.
Aby obsłużyć zarówno skalary, jak i obiekty, możesz to zrobić:
źródło
ECMAScript 6 ma elegancką propozycję znalezienia.
Oto dokumentacja MDN na ten temat.
Funkcja wyszukiwania działa w ten sposób.
Możesz użyć tego w ECMAScript 5 i poniżej, definiując funkcję .
źródło
Chociaż
array.indexOf(x)!=-1
jest to najbardziej zwięzły sposób na zrobienie tego (i jest obsługiwany przez przeglądarki inne niż Internet Explorer od ponad dekady ...), nie jest to O (1), ale raczej O (N), co jest okropne. Jeśli tablica się nie zmieni, możesz przekonwertować tablicę na tablicę mieszającą, a następnie wykonajtable[x]!==undefined
lub===undefined
:Próbny:
(Niestety, chociaż możesz utworzyć Array.prototype.contains, aby „zamrozić” tablicę i przechowywać tablicę hashtable w this._cache w dwóch wierszach, dałoby to złe wyniki, jeśli zdecydujesz się edytować tablicę później. JavaScript nie ma wystarczających zaczepów, aby pozwala zachować ten stan, w przeciwieństwie do Pythona na przykład.)
źródło
Można użyć zestawu, który ma metodę „has ()”:
źródło
return proxy.has(obj)
jest o wiele czystszy niż dwie linijki z oświadczeniem if-else tutajfunction contains(arr, obj) { return new Set(arr).has(obj); }
Posługiwać się:
Próbny
Aby dokładnie wiedzieć, co
tilde
~
robić w tym momencie, zapoznaj się z tym pytaniem. Co robi tylda, gdy poprzedza wyrażenie? .źródło
OK, możesz po prostu zoptymalizować swoje kod, aby uzyskać wynik!
Jest wiele sposobów na zrobienie tego, które są czystsze i lepsze, ale chciałem tylko uzyskać wzór i zastosować się do tego
JSON.stringify
, po prostu zrób coś takiego w twoim przypadku:źródło
contains([{ a: 1, b: 2 }], { b: 2, a: 1 })
ponieważ obiekty strunowe zachowują kolejność właściwości.W żadnym razie nie najlepszy, ale byłem kreatywny i uzupełniałem repertuar.
Nie używaj tego
źródło
Zaskoczony, że do tego pytania wciąż nie dodano najnowszej składni, dodając moje 2 centy.
Powiedzmy, że mamy tablicę Object arrObj i chcemy w niej wyszukać obj.
Array.prototype. indexOf -> (zwraca indeks lub -1 ) jest zwykle używany do znajdowania indeksu elementu w tablicy. Można to również wykorzystać do wyszukiwania obiektu, ale działa tylko wtedy, gdy przekazujesz odwołanie do tego samego obiektu.
Array.prototype. zawiera -> (zwraca wartość prawda lub fałsz )
Array.prototype. find -> (przyjmuje callback, zwraca pierwszą wartość / obiekt, który zwraca true w CB).
Array.prototype. findIndex -> (przyjmuje callback, zwraca indeks pierwszej wartości / obiektu, który zwraca true w CB).
Ponieważ find i findIndex przyjmuje wywołanie zwrotne, możemy pobrać dowolny obiekt (nawet jeśli nie mamy referencji) z tablicy, twórczo ustawiając prawdziwy warunek.
źródło
Wykorzystuje się proste rozwiązanie tego wymagania
find()
Jeśli masz szereg obiektów takich jak poniżej,
Następnie możesz sprawdzić, czy obiekt z twoją wartością jest już obecny, czy nie
jeśli dane są zerowe, to nie ma administratora, w przeciwnym razie zwróci istniejący obiekt jak poniżej.
Następnie możesz znaleźć indeks tego obiektu w tablicy i zastąpić go, używając poniższego kodu.
otrzymasz wartość jak poniżej
mam nadzieję, że to pomoże każdemu.
źródło
źródło