Soru Bir dizinin JavaScript'te bir nesne içerip içermediğini nasıl kontrol edebilirim?


Bir JavaScript dizisinin bir nesne içerip içermediğini öğrenmenin en özlü ve etkili yolu nedir?

Bunu yapmak için bildiğim tek yol budur:

function contains(a, obj) {
    for (var i = 0; i < a.length; i++) {
        if (a[i] === obj) {
            return true;
        }
    }
    return false;
}

Bunu başarmak için daha iyi ve daha özlü bir yolu var mı?

Bu, Stack Overflow sorusuyla yakından ilgilidir. JavaScript Dizisinde bir öğeyi bulmanın en iyi yolu? kullanarak bir dizide nesneleri bulma adresleri indexOf.


3226
2017-10-25 22:14


Menşei


Sadece test edildi: yolun aslında tarayıcılar arasında en hızlı olanıdır: jsperf.com/find-element-in-obj-vs-array/2 ($ .inArray'da olduğu gibi) indexOf kullanırken çok daha yavaştır (bir değişkende a.length önyükleme dışında) - Jörn Berkefeld
Birçoğu Array # indexOf'un burada en iyi seçim olduğunu söyledi. Ancak, Boole'ye doğru şekilde gönderilebilecek bir şey istiyorsanız, şunu kullanın: ~[1,2,3].indexOf(4) yanlış olarak değerlendirecek 0 dönecek, ~[1,2,3].indexOf(3) doğru olarak değerlendirecek -3 dönecektir. - lordvlad
~ ihtiyacınız olan şey için bir boole dönüştürmek için kullanmak istediğiniz şey değil !. Ama bu durumda -1 ile eşitliği kontrol etmek istiyorsun, o zaman işlev bitebilirreturn [1,2,3].indexOf(3) === -1;  ~ bir ikili değil, her bir bitin değerini tek tek tersine çevirecektir. - mcfedr
@Iordvlad [1,2,3].indexOf(4) aslında olacak -1 dönüş. @Mcfedr'ın işaret ettiği gibi, ~ öyle mi bitwise-NOT operatörübakınız ES5 11.4.8. Şey, ikili temsilinden beri -1 sadece 1'den oluşur, tamamlayıcı 0, yanlış olarak değerlendirir. Başka bir sayının tamamlayıcısı sıfırdan, dolayısıyla doğru olacaktır. Yani, ~ sadece iyi çalışır ve genellikle birlikte kullanılır indexOf. - mknecht
Başlık yanıltıcıdır. Nerede [[1,2],[3,4]].includes([3,4]) ? - mplungjan


Cevaplar:


Mevcut tarayıcılar Array#includes, hangi yapar kesinlikle o yaygın olarak desteklenirve bir polyfill eski tarayıcılar için.

> ['joe', 'jane', 'mary'].includes('jane');
true 

Ayrıca kullanabilirsiniz Array#indexOfDaha az doğrudan, ancak güncel olmayan tarayıcılar için Polyfills gerektirmez.

jQuery sunuyor $.inArrayişlevsel olarak eşdeğerdir Array#indexOf.

underscore.js, bir JavaScript yardımcı kitaplığı sunuyor _.contains(list, value), takma ad _.include(list, value), her ikisi de indeksi Bir JavaScript dizisini geçtiğinde dahili olarak.

Diğer bazı çerçeveler benzer yöntemler sunar:

Bazı çerçevelerin bunu bir işlev olarak uyguladığına dikkat edin, diğerleri ise işlevi dizi prototipine ekler.


3650
2017-10-25 23:10



MooTools ayrıca, gerçek soruya benzeyen bir boolean döndüren Array.contains'a sahiptir. - Ryan Florence
prototip ayrıca Array.include bu bir boole döndürür - user102008
İyi bir tarayıcı kullanıyorsanız, sadece kullanabilirsiniz array.indexOf(object) != -1 - Sam Soffes
Ayrıca, indexOf'u bir koşul olarak tek başına kullanmayın, çünkü ilk eleman 0'a döner ve falsi olarak değerlendirilir - plus-
inArray öğenin dizinini döndüren bir işlev için korkunç bir addır ve -1 eğer mevcut değilse. Bir booleanın iade edilmesini beklerdim. - Tim


Güncelleme: Yorumlarda yorumdan bahsedildiği gibi, bağlantılı ölçüt 2008 yılında yapılmıştır, bu nedenle sonuçlar modern tarayıcılar için uygun olmayabilir. Ancak, muhtemelen modern olmayan tarayıcıları desteklemek için buna ihtiyacınız vardır ve muhtemelen o zamandan beri güncellenmemiştir. Her zaman kendiniz için test edin.

Diğerleri söylediler, dizi boyunca yineleme muhtemelen en iyi yoldur, ama kanıtlanmış bu azalan while döngü, JavaScript'te yinelemenin en hızlı yoludur. Bu yüzden kodunuzu aşağıdaki gibi yeniden yazmak isteyebilirsiniz:

function contains(a, obj) {
    var i = a.length;
    while (i--) {
       if (a[i] === obj) {
           return true;
       }
    }
    return false;
}

Elbette, Array prototipini de genişletebilirsiniz:

Array.prototype.contains = function(obj) {
    var i = this.length;
    while (i--) {
        if (this[i] === obj) {
            return true;
        }
    }
    return false;
}

Ve şimdi sadece aşağıdakileri kullanabilirsiniz:

alert([1, 2, 3].contains(2)); // => true
alert([1, 2, 3].contains('2')); // => false

357
2017-10-25 22:49



Ama dikkat et: stackoverflow.com/questions/237104/javascript-array-containsobj/... - MatrixFrog
"Kanıtlanmış" güçlü bir kelimedir. JS motorları sürekli gelişir ve 3 yıl önce ölçülen uygulama süresi son derece modası geçmiş. - orip
@Damir - Katılıyorum. Mümkünse indexOf'u kullanmak için örneği değiştirin, bu yüzden insanlar bu kodu körü körüne yapıştırarak yapabilecekleri en iyi performansı elde edeceklerdir. - orip
@cbmeeks evet, kesinlikle bakım gerekiyor. Muhtemelen bir dava oldu for (o in array) genellikle dizi boyunca döngü yaparken yapılmaması gereken ... - Damir Zekić
Bunu yapmanın en iyi yolu, [1, 2, 3] .indexOf (1)> -1 olup olmadığını kontrol etmektir. - Devin G Rhode


indexOf belki de, "ECMA-262 standardına göre bir JavaScript uzantısıdır, çünkü standardın diğer uygulamalarında mevcut olmayabilir."

Örnek:

[1, 2, 3].indexOf(1) => 0
["foo", "bar", "baz"].indexOf("bar") => 1
[1, 2, 3].indexOf(4) => -1

AFAICS Microsoft değil bir çeşit alternatif sunmak Buna ek olarak, Internet Explorer'da (ve desteklemeyen diğer tarayıcılarda) dizilere benzer işlevler ekleyebilirsiniz. indexOf) eğer isterseniz hızlı Google araması açığa çıkar (Örneğin, Bu).


156
2018-01-01 01:40



aslında, bağlandığınız developer.mozilla.org sayfasında onu desteklemeyen tarayıcılar için indexOf uzantısının bir uygulamasının bir örneği vardır. - Lloyd Cotten
Aslında, onu desteklemeyen tarayıcılar için (örneğin IE7) Array prototipine indeks eklediğinizde, bunlar dizideki öğeler arasında döngü yaparken de bu işlevin üstesinden gelmeyi deneyeceklerdir. pis. - CpILL
IE9 şimdi bunu destekliyor - Liam
Nesne kontrol etmek için uygulanabilir mi? Nesne durumunda işe yaramaz sanmıyorum - Himesh Aadeshara


ECMAScript 7 tanıtıyor Array.prototype.includes.

Bu şekilde kullanılabilir:

[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false

Ayrıca isteğe bağlı ikinci bir argümanı kabul eder fromIndex:

[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true

aksine indexOf, hangi kullanır Sıkı Eşitlik Karşılaştırması, includes kullanarak karşılaştırır SameValueZero eşitlik algoritması. Bu, bir dizi içerip içermediğini algılayabileceğiniz anlamına gelir. NaN:

[1, 2, NaN].includes(NaN); // true

Ayrıca farklı indexOf, includes eksik endeksleri atlamıyor:

new Array(5).includes(undefined); // true

Şu anda hala bir taslak ama olabilir polyfilledTüm tarayıcılarda çalışmasını sağlamak için.


128
2018-03-24 04:59



IE ve Microsfot Edge için desteklenmiyor (2015) (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...) - Adriano Resende
Ayrıca ilgili, ES7 uyumluluk tablosu (Şimdi krom destekliyor gibi görünüyor) - styfle
Buna göre, Node 6+ sürümünde destekleniyor. node.green - Ryan
Nesne kontrol etmek için uygulanabilir mi? Nesne durumunda işe yaramaz sanmıyorum - Himesh Aadeshara


b değer ve a dizi. Döner true veya false:

function(a, b) {
    return a.indexOf(b) != -1
}

96
2017-10-27 00:38



Bu kısım anlamıyorum "!! ~". Ve IE8'de çalışmaz, çünkü IE8 dizisi Archo nesnesi üzerinde indexOf () işlevini desteklemiyor. - svlada
"~", 1'i bir sayıdan katlar, dönüştürür ve çıkarır. indexOf -1 başarısız olur, böylece "~" -1 değerini "0" a çevirir. "!!" kullanarak sayıları bolelere çevirir (!! 0 === false) - william malo
aynı performans! = - 1 jsperf.com/indexof-check - aelgoa
Sadece bir parça atış, ağzımda. Kesinlikle profesyonel olmayan kod. - Michael Cole
Boolean operatörlerinin profesyonel olmayan etkileri hakkında bilgi eksikliği diyebilirim. Ama okunabilir kodun değerini kabul ediyorum, kesinlikle bunu açıkça etiketlenmiş bir işleve sarmak istiyorum. Ve bu, çoğu büyük JS çerçevesinin yaptığı şeydir. - Fx32


İşte bir JavaScript 1.6 uyumlu uygulanması Array.indexOf:

if (!Array.indexOf)
{
  Array.indexOf = [].indexOf ?
      function (arr, obj, from) { return arr.indexOf(obj, from); }:
      function (arr, obj, from) { // (for IE6)
        var l = arr.length,
            i = from ? parseInt( (1*from) + (from<0 ? l:0), 10) : 0;
        i = i<0 ? 0 : i;
        for (; i<l; i++) {
          if (i in arr  &&  arr[i] === obj) { return i; }
        }
        return -1;
      };
}

65
2017-09-13 17:32



Bu harika görünüyor, ama biraz şaşkın: * 1 ve 3 numaralı eşdeğer testler değil mi? * Prototipi test etmek ve gerekirse Array.prototype işlevini eklemek daha iyi olmaz mıydı? - Avi Flax
Onlar eşit değiller. [].indexOf için kısa yol Array.prototype.indexOf. Paranoid-savunmasız Javascript programcıları yerli prototipleri tüm maliyetlerde uzatmaktan kaçınırlar. - Már Örlygsson
değil [].indexOf yeni bir dizi oluşturup daha sonra erişmek indexOf, Iken Array.prototype.indexOf sadece prototipe doğrudan erişir? - alex
@alex evet [].indexOf === Array.prototype.indexOf (FireBug'da deneyin), aksine [].indexOf !== Array.indexOf. - Már Örlygsson


kullanın:

function isInArray(array, search)
{
    return array.indexOf(search) >= 0;
}

// Usage
if(isInArray(my_array, "my_value"))
{
    //...
}

46
2017-08-27 16:45



x ? true : false genellikle gereksizdir. Burada. - Ry-♦
@minitech Neden gereksiz olduğunu söylüyorsunuz? - Matías Cánepa
array.indexOf(search) >= 0 zaten bir boole. Sadece return array.indexOf(search) >= 0. - Ry-♦
@minitech iyi teşekkürler! Aslında böyle bir inşaatın iade edilebileceğini bilmiyordum. TIL yeni bir şey. - Matías Cánepa
Javascript'in tam anlamıyla herhangi bir yapısı iade edilebilir. - B T


JavaScript'i genişletme Array Nesne çok kötü bir fikir çünkü yeni özellikleri (özel yöntemlerinizi) for-in Mevcut betikleri bozabilecek döngüler. Birkaç yıl önce yazarların Prototip Kütüphane, kütüphane uygulamalarını yeniden yapılandırmak zorunda kaldı.

Sayfanızda çalışan diğer JavaScript'lerle uyumluluk hakkında endişelenmenize gerek yoksa, bunun için gidin, daha garip, ancak daha güvenli bağımsız fonksiyon çözümünü tavsiye ederim.


38
2017-07-18 14:36



Katılmıyorum. For-in döngüleri tam olarak bu nedenle diziler için kullanılmamalıdır. Popüler js kitaplıklarından birini kullanırken for-in döngüleri kullanmak kesilir - Tomas
Bu maymun yama olarak kabul edilir mi? lol Bazı insanlar böyle. - cbmeeks