Bir dizinin JavaScript'te bir değer içerip içermediğini nasıl kontrol ederim?


3996

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

Bunu yapmanın tek yolu bu:

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

Bunu başarmanın daha iyi ve daha özlü bir yolu var mı?

Bu, Yığın Taşması sorusuyla çok yakından ilgilidir. JavaScript Dizisindeki bir öğeyi bulmanın en iyi yolu nedir? kullanarak bir dizideki nesneleri bulma indexOf.


49
az önce test edildi: yolunuz aslında tarayıcılar arasında en hızlı olanıdır : indexOf kullanırken ($ gibi) jsperf.com/find-element-in-obj-vs-array/2 .inArray) çok daha yavaş
Jörn Berkefeld

17
birçoğu, Array # indexOf'un burada en iyi seçiminiz olduğunu söyledi. Ancak Boolean'a doğru şekilde dökülebilecek bir şey istiyorsanız, bunu kullanın: ~[1,2,3].indexOf(4)yanlış olarak değerlendirilecek 0 döndürür, oysa ~[1,2,3].indexOf(3)doğru olarak değerlendirecek -3 döndürür.
lordvlad

8
~bir boole dönüştürmek için kullanmak istediğiniz şey değildir, bunun için ihtiyacınız !. Ancak bu durumda -1 ile eşitliği kontrol etmek istersiniz, bu nedenle işlev return [1,2,3].indexOf(3) === -1; ~bir ikili değildir, değerin her bitini ayrı ayrı tersine çevirir.
mcfedr

14
@Iordvlad [1,2,3].indexOf(4)aslında -1 döndürür . @Mcfedr'in işaret ettiği gibi ~, bitsel-NOT operatörüdür , bkz. ES5 11.4.8. Şey, ikili gösterim -1sadece 1'lerden oluştuğu için 0, tamamlayıcı olan ve yanlış olarak değerlendirilir. Başka herhangi bir sayının tamamlayıcısı sıfırdan farklı olacaktır, dolayısıyla doğrudur. Yani, ~gayet iyi çalışıyor ve genellikle birlikte kullanılır indexOf.
mknecht

5
Başlık yanıltıcı. Nerede [[1,2],[3,4]].includes([3,4])?
mplungjan

Yanıtlar:


4375

Modern tarayıcılar Array#includes, tam olarak bunu yapar ve IE dışındaki herkes tarafından yaygın olarak desteklenir :

console.log(['joe', 'jane', 'mary'].includes('jane')); //true

Daha Array#indexOfaz doğrudan olan, ancak eski tarayıcılar için çoklu dolgular gerektirmeyen de kullanabilirsiniz .


Birçok çerçeve de benzer yöntemler sunar:

Bazı çerçevelerin bunu bir işlev olarak uygularken, bazılarının işlevi dizi prototipine eklediğine dikkat edin.


42
MooTools ayrıca Array.contain, burada gerçek soruya benzeyen bir boolean döndürür.
Ryan Florence

22
prototip ayrıca Array.includebir boolean döndürür
user102008

46
İyi bir tarayıcı kullanıyorsanız, sadece kullanabilirsinizarray.indexOf(object) != -1
Sam Soffes

13
Ayrıca, ilk öğe 0 döndüreceği ve falsy
artı

241
inArrayöğenin dizinini döndüren ve -1yoksa bir işlev için korkunç bir addır . Bir boolean döndürülmesini beklenir.
Tim

434

2019'dan güncelleme: Bu cevap 2008'den (11 yaşında!) Geliyor ve modern JS kullanımı ile ilgili değil. Vaat edilen performans artışı, o zamanın tarayıcılarında yapılan bir karşılaştırmaya dayanıyordu. Modern JS yürütme bağlamlarıyla ilgili olmayabilir. Kolay bir çözüme ihtiyacınız varsa, diğer yanıtları arayın. En iyi performansa ihtiyacınız varsa, ilgili yürütme ortamlarında kendiniz için karşılaştırma yapın.

Diğerlerinin söylediği gibi, dizi boyunca yineleme muhtemelen en iyi yoldur, ancak azalan bir döngünün JavaScript'te yinelemenin en hızlı yolu olduğu kanıtlanmıştırwhile . Bu nedenle, 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;
}

Tabii ki, 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 aşağıdakileri kullanabilirsiniz:

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


22
"Kanıtlanmış" güçlü bir kelimedir. JS motorları sürekli gelişir ve 3 yıl önce ölçülen çalışma süresi çok eskidir.
8'de orip

2
@Damir - Katılıyorum. Mümkünse, örneği indexOf kullanacak şekilde değiştirin, böylece bu kodu körü körüne yapıştıracak insanlar ellerinden gelenin en iyisini alacaktır.
orip

1
@cbmeeks evet, bakıma kesinlikle ihtiyaç var. Muhtemelen for (o in array)genellikle dizi boyunca döngü yaparken yapılmaması gereken bir
durumdu

1
Bunu yapmanın en iyi yolu [1, 2, 3] .indexOf (1)> -1
Devin G Rhode

207

indexOf belki, ancak bu "ECMA-262 standardının JavaScript uzantısıdır; bu nedenle standardın diğer uygulamalarında mevcut olmayabilir."

Misal:

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

AFAICS Microsoft buna bir çeşit alternatif sunmuyor , ancak hızlı bir Google aramasının gösterdiğiindexOf gibi (örneğin, bu ) Internet Explorer'daki (ve desteklemeyen diğer tarayıcıların) dizilere benzer işlevler ekleyebilirsiniz. ).


aslında, bağladığınız developer.mozilla.org sayfasında onu desteklemeyen tarayıcılar için indexOf uzantısının uygulanmasına bir örnek vardır.
Lloyd Cotten

aslında, desteklemeyen tarayıcılar için Array prototipine indexof eklerseniz (yani IE7), dizideki öğeler arasında döngü yaparken bu işlev üzerinde döngü oluşturmaya çalışırlar. pis.
CpILL


Nesneyi kontrol etmek uygulanabilir mi? Nesne durumunda çalıştığını sanmıyorum
Himesh Aadeshara

169

ECMAScript 7 tanıtır 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ı da kabul eder fromIndex:

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

Farklı olarak indexOfkullanan, Katı Eşitlik Karşılaştırma , includeskullanarak karşılaştırır SameValueZero eşitlik algoritması. Bu, bir dizinin aşağıdakileri içerip içermediğini tespit edebileceğiniz anlamına gelir NaN:

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

Ayrıca aksine indexOf, includeseksik endeksleri atlamaz:

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

Şu anda hala bir taslak, ancak tüm tarayıcılarda çalışması için çoklu doldurulabilir .


3
IE ve Microsfot Edge (2015) için desteklenmez ( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… )
Adriano Resende

1
Ayrıca alakalı, ES7 uyumluluk tablosu (krom şimdi destekliyor gibi görünüyor)
styfle

Nesneyi kontrol etmek uygulanabilir mi? Nesne durumunda çalıştığını sanmıyorum
Himesh Aadeshara

128

En iyi yanıtlar ilkel türleri varsayar, ancak bir dizinin bazı özelliklere sahip bir nesne içerip içermediğini öğrenmek istiyorsanız , Array.prototype.some () çok zarif bir çözümdür:

const items = [ {a: '1'}, {a: '2'}, {a: '3'} ]

items.some(item => item.a === '3')  // returns true
items.some(item => item.a === '4')  // returns false

Bununla ilgili güzel olan şey, elemanın bulunmasından sonra yinelemenin durdurulmasıdır, böylece gereksiz yineleme döngüleri korunur.

Ayrıca, ifbir boole döndürdüğü için bir ifadeye çok iyi uyuyor :

if (items.some(item => item.a === '3')) {
  // do something
}

* Reçel yorumda belirtildiği gibi, bu cevap sırasında, Eylül 2018, Array.prototype.some()tamamen desteklenmektedir: caniuse.com destek tablosu


1
Bugün itibarıyla, Eylül 2018, Array.prototype.some () tamamen desteklenmektedir: caniuse.com destek tablosu
jamess

1
AWS Node.js Lambda için Düğümde> = 8.10 çalışmak, bu yüzden bu harika. Çok temiz ve basit bir çözüm! --🏻
Ürdün

1
@jamess İyi desteklenebilir, ancak Arrow functionsbu örnekte o kadar iyi desteklenmediğini unutmayın. Daha fazla ayrıntı için buraya bakın: developer.mozilla.org/tr-TR/docs/Web/JavaScript/Reference/…
Kamil Witkowski

Kısa devre yapıyor mu? Yoksa bir değer bulsa bile tüm diziyi yineliyor mu?
Douglas Gaskell

@ DouglasGaskell bir kez bulunan yinelemeyi iptal eder (cevapta belirtilir)
Michael

112

Diyelim ki böyle bir dizi tanımladınız:

const array = [1, 2, 3, 4]

Aşağıda, orada bir olup olmadığını kontrol etmenin üç yolu 3vardır. Bunların tümü ya dönmek trueveya false.

Yerel Dizi yöntemi (ES2016'dan beri) ( uyumluluk tablosu )

array.includes(3) // true

Özel Dizi yöntemi olarak (ES2016 öncesi)

// Prefixing the method with '_' to avoid name clashes
Object.defineProperty(Array.prototype, '_includes', { value: function (v) { return this.indexOf(v) !== -1 }})
array._includes(3) // true

Basit fonksiyon

const includes = (a, v) => a.indexOf(v) !== -1
includes(array, 3) // true

Eğer "b" dizisi "a" ise doğru döner ... Bunu nasıl açıklayacağımı bilmiyorum ...
william malo

4
Bu kısmı anlamıyorum "!! ~". Ve IE8 Array nesnesinde indexOf () desteklemediği için bu IE8 çalışmaz düşünüyorum.
svlada

62
"~", 1'i katlar, tersine çevirir ve 1'den çıkarır. indexOf başarısız olursa -1 döndürür, bu nedenle "~" -1'i "0" a çevirir. "!!" kullanarak sayıları boleans'e dönüştürür (!! 0 === yanlış)
william malo

1
"> -1" .length === yana 1, "!! ~" .length - Serin, ama ciddi basitlik y uğruna, sadece a.indexOf (b)> için
süper

2
Boole operatörlerinin profesyonel olmayan etkileri hakkında bilgi eksikliğini söyleyebilirim. Ama okunabilir kodun değeri konusunda hemfikirim, kesinlikle bunu açıkça etiketlenmiş bir fonksiyonda sararım. Ve çoğu JS çerçevesinin yaptığı da aynen bu.
okdewit

79

İşte bir JavaScript 1.6 uyumlu uygulaması 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;
        };
}

Bu harika görünüyor, ancak biraz karışık: * 1. ve 3. satırlardaki testler eşdeğer değil mi? * Prototipi test etmek ve gerekirse Array.prototype işlevini eklemek daha iyi olmaz mıydı?
Avi Flax

10
Eşdeğer değiller. [].indexOfkestirme yoludur Array.prototype.indexOf. Paranoyak savunmalı Javascript programcıları yerel prototipleri her ne pahasına olursa olsun uzatmaktan kaçınırlar.
Már Örlygsson

1
Is not [].indexOfyeni bir dizi oluşturarak ve ardından erişen indexOfiken, Array.prototype.indexOfsadece doğrudan prototipi erişir?
alex

3
@alex evet [].indexOf === Array.prototype.indexOf( FireBug'da deneyin), ancak tam tersi [].indexOf !== Array.indexOf.
Már Örlygsson

57

kullanın:

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

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

25
x ? true : falsegenellikle gereksizdir. Burada.
Ry-

@minitech Neden gereksiz olduğunu söylüyorsun?
Matías Cánepa

8
array.indexOf(search) >= 0zaten bir boole. Sadece return array.indexOf(search) >= 0.
Ry-

@ minitech teşekkürler! Aslında böyle bir yapının iade edilebileceğini bilmiyordum. TIL yeni bir şey.
Matías Cánepa

Kelimenin tam anlamıyla javascript içindeki herhangi bir yapı iade edilebilir
BT

49

JavaScript Arraynesnesini genişletmek gerçekten kötü bir fikir çünkü for-inmevcut komut dosyalarını bozabilecek döngülere yeni özellikler (özel yöntemleriniz) ekliyorsunuz. Birkaç yıl önce Prototip kütüphanesinin yazarları, sadece bu tür şeyleri kaldırmak için kütüphane uygulamalarını yeniden tasarlamak zorunda kaldılar.

Sayfanızda çalışan diğer JavaScriptlerle uyumluluk konusunda endişelenmenize gerek yoksa, bunun için gidin, aksi takdirde, daha garip ama daha güvenli bağımsız işlev çözümünü öneriyorum.


22
Katılmıyorum. For-in döngüleri tam da bu nedenle diziler için kullanılmamalıdır. Popüler js kütüphanelerinden birini kullanırken for-in döngülerini kullanmak kırılacaktır
Tomas

Bu maymun yaması olarak kabul edilir mi? lol Bazı insanlar böyle.
cbmeeks

33

Tek astarı:

function contains(arr, x) {
    return arr.filter(function(elem) { return elem == x }).length > 0;
}

8
array.filter(e=>e==x).length > 0eşdeğer array.some(e=>e==x)ama somedaha etkili
Apolo


28

Aşağıdakileri kullanıyorum:

Array.prototype.contains = function (v) {
    return this.indexOf(v) > -1;
}

var a = [ 'foo', 'bar' ];

a.contains('foo'); // true
a.contains('fox'); // false


19

Umarım daha hızlı çift yönlü indexOf/ lastIndexOfalternatif

2015

Yeni yöntem içeren çok güzel olsa da , destek şimdilik sıfırdır.

Uzun bir süre yavaş indexOf / lastIndexOf işlevlerini değiştirmenin yolunu düşünüyordum.

En iyi cevaplara bakıldığında zaten başarılı bir yol bulundu. Onlardan contains@Damir Zekic tarafından gönderilen ve en hızlı olması gereken işlevi seçtim . Ama aynı zamanda kriterlerin 2008'den beri olduğunu ve bu yüzden modası geçmiş olduğunu belirtiyor.

Ben de tercih whileüzerinde fordeğil, belirli bir nedenle ben bir for döngüsü ile işlev yazma sona erdi. Ayrıca a ile de yapılabilir while --.

Bunu yaparken dizinin her iki tarafını da kontrol edersem yinelemenin çok daha yavaş olup olmadığını merak ettim. Görünüşe göre hayır, bu yüzden bu işlev en çok oy alanlardan iki kat daha hızlı. Tabii ki yerli olandan da daha hızlı. Bu, aradığınız değerin dizinin başında mı yoksa sonunda mı olduğunu asla bilemeyeceğiniz gerçek bir dünya ortamında.

Sadece bir değere sahip bir dizi ittiğinizi bildiğinizde, lastIndexOf'u kullanmak muhtemelen en iyi çözüm olmaya devam eder, ancak büyük dizilerden geçmeniz gerekiyorsa ve sonuç her yerde olabilirse, işleri daha hızlı hale getirmek için sağlam bir çözüm olabilir.

Çift yönlü dizinOf / lastIndexOf

function bidirectionalIndexOf(a, b, c, d, e){
  for(c=a.length,d=c*1; c--; ){
    if(a[c]==b) return c; //or this[c]===b
    if(a[e=d-1-c]==b) return e; //or a[e=d-1-c]===b
  }
  return -1
}

//Usage
bidirectionalIndexOf(array,'value');

Performans testi

http://jsperf.com/bidirectionalindexof

Test olarak 100k girişli bir dizi oluşturdum.

Üç sorgu: başında, ortasında ve dizinin sonunda.

Umarım bunu ilginç bulursunuz ve performansı test edersiniz.

Not: Ben biraz değiştirilmiş görebileceğiniz gibi contains(yani temelde indexOf & lastIndexOf çıkışını yansıtacak şekilde işlev trueile indexve falseile -1). Bu ona zarar vermemeli.

Dizi prototipi değişkeni

Object.defineProperty(Array.prototype,'bidirectionalIndexOf',{value:function(b,c,d,e){
  for(c=this.length,d=c*1; c--; ){
    if(this[c]==b) return c; //or this[c]===b
    if(this[e=d-1-c] == b) return e; //or this[e=d-1-c]===b
  }
  return -1
},writable:false, enumerable:false});

// Usage
array.bidirectionalIndexOf('value');

İşlev, doğru ya da yanlış ya da nesne, dize ya da her neyse döndürmek için kolayca değiştirilebilir.

Ve işte whilevaryant:

function bidirectionalIndexOf(a, b, c, d){
  c=a.length; d=c-1;
  while(c--){
    if(b===a[c]) return c;
    if(b===a[d-c]) return d-c;
  }
  return c
}

// Usage
bidirectionalIndexOf(array,'value');

Bu nasıl mümkün olabilir?

Bir dizide yansıyan indeksi elde etmek için basit hesaplama, gerçek bir döngü yineleme yapmaktan iki kat daha hızlı olduğunu düşünüyorum.

İşte yineleme başına üç kontrol yapan karmaşık bir örnek, ancak bu sadece kodun yavaşlamasına neden olan daha uzun bir hesaplama ile mümkündür.

http://jsperf.com/bidirectionalindexof/2


18

Verim

Bugün 2020.01.07 Chrome v78.0.0, Safari v13.0.4 ve Firefox v71.0.0'da seçilen 15 çözüm için MacOs HighSierra 10.13.6 üzerinde testler gerçekleştiriyorum. Sonuçlar

  • çözeltiler göre JSON, Setve şaşırtıcı bir şekilde find(R, N, O) tüm tarayıcılarda yavaş vardır
  • es6 includes(F) yalnızca kromda hızlıdır
  • for(C, D) ve indexOf(G, H) tabanlı çözümler küçük ve büyük dizilerdeki tüm tarayıcılarda oldukça hızlıdır, bu nedenle etkili çözüm için muhtemelen en iyi seçimdir
  • döngü sırasında indeksin azaldığı çözümler, (B) muhtemelen CPU önbelleğinin çalışması nedeniyle daha yavaştır .
  • Ayrıca, aranan öğe dizi uzunluğunun% 66 pozisyonundayken büyük dizi için test çalıştırıyorum ve for(C, D, E) 'ye dayalı çözümler benzer sonuçlar veriyor (~ 630 ops / sn - ama safari ve firefox'taki E 10'du. C ve D'den% 20 daha yavaş)

Sonuçlar

resim açıklamasını buraya girin

ayrıntılar

2 test örneği gerçekleştiriyorum: 10 elemanlı dizi ve 1 milyon elemanlı dizi için. Her iki durumda da aranan öğeyi dizinin ortasına koyarız.

Küçük dizi - 10 eleman

BURADA makinenizde testler yapabilirsiniz

resim açıklamasını buraya girin

Büyük dizi - 1.000.000 öğe

BURADA makinenizde testler yapabilirsiniz

resim açıklamasını buraya girin


16

JavaScript 1.6 veya üstünü (Firefox 1.5 veya üstünü) kullanıyorsanız Array.indexOf'u kullanabilirsiniz . Aksi takdirde, orijinal kodunuza benzer bir şeyle sonuçlanacağınızı düşünüyorum.


16
function inArray(elem,array)
{
    var len = array.length;
    for(var i = 0 ; i < len;i++)
    {
        if(array[i] == elem){return i;}
    }
    return -1;
} 

Bulunursa dizi dizinini veya bulunmazsa -1 değerini döndürür


16

Bu snippet'i kullanıyoruz (nesnelerle, dizilerle, dizelerle çalışır):

/*
 * @function
 * @name Object.prototype.inArray
 * @description Extend Object prototype within inArray function
 *
 * @param {mix}    needle       - Search-able needle
 * @param {bool}   searchInKey  - Search needle in keys?
 *
 */
Object.defineProperty(Object.prototype, 'inArray',{
    value: function(needle, searchInKey){

        var object = this;

        if( Object.prototype.toString.call(needle) === '[object Object]' || 
            Object.prototype.toString.call(needle) === '[object Array]'){
            needle = JSON.stringify(needle);
        }

        return Object.keys(object).some(function(key){

            var value = object[key];

            if( Object.prototype.toString.call(value) === '[object Object]' || 
                Object.prototype.toString.call(value) === '[object Array]'){
                value = JSON.stringify(value);
            }

            if(searchInKey){
                if(value === needle || key === needle){
                return true;
                }
            }else{
                if(value === needle){
                    return true;
                }
            }
        });
    },
    writable: true,
    configurable: true,
    enumerable: false
});

Kullanımı:

var a = {one: "first", two: "second", foo: {three: "third"}};
a.inArray("first");          //true
a.inArray("foo");            //false
a.inArray("foo", true);      //true - search by keys
a.inArray({three: "third"}); //true

var b = ["one", "two", "three", "four", {foo: 'val'}];
b.inArray("one");         //true
b.inArray('foo');         //false
b.inArray({foo: 'val'})   //true
b.inArray("{foo: 'val'}") //false

var c = "String";
c.inArray("S");        //true
c.inArray("s");        //false
c.inArray("2", true);  //true
c.inArray("20", true); //false

15

Bir dizide bir nesnenin varlığını tekrar tekrar kontrol ediyorsanız,

  1. Dizinizde ekleme sıralaması yaparak diziyi her zaman sıralı tutma (yeni nesneleri doğru yere koyun)
  2. Güncelleme nesnelerini kaldırma + sıralı ekleme işlemi olarak yapma ve
  3. Bilgisayarınızda bir ikili arama araması kullanın contains(a, obj).

2
Ya da mümkünse, bir Dizi kullanmayı tamamen bırakın ve bunun yerine MattMcKnight ve ninjagecko'nun önerdiği gibi sözlük olarak bir Nesne kullanın.
joeytwiddle

13

Tüm modern tarayıcılarda çalışan çözüm:

function contains(arr, obj) {
  const stringifiedObj = JSON.stringify(obj); // Cache our object to not call `JSON.stringify` on every iteration
  return arr.some(item => JSON.stringify(item) === stringifiedObj);
}

Kullanımı:

contains([{a: 1}, {a: 2}], {a: 1}); // true

IE6 + çözümü:

function contains(arr, obj) {
  var stringifiedObj = JSON.stringify(obj)
  return arr.some(function (item) {
    return JSON.stringify(item) === stringifiedObj;
  });
}

// .some polyfill, not needed for IE9+
if (!('some' in Array.prototype)) {
  Array.prototype.some = function (tester, that /*opt*/) {
    for (var i = 0, n = this.length; i < n; i++) {
      if (i in this && tester.call(that, this[i], i, this)) return true;
    } return false;
  };
}

Kullanımı:

contains([{a: 1}, {a: 2}], {a: 1}); // true

Neden kullanılır JSON.stringify?

Array.indexOfve Array.includes(ve buradaki cevapların çoğu) sadece referans ile karşılaştırır, değerle karşılaştırmaz.

[{a: 1}, {a: 2}].includes({a: 1});
// false, because {a: 1} is a new object

Bonus

Optimize edilmemiş ES6 tek astar:

[{a: 1}, {a: 2}].some(item => JSON.stringify(item) === JSON.stringify({a: 1));
// true

Not: Anahtarlar aynı sıradaysa, nesneleri değere göre karşılaştırmak daha iyi çalışır, bu nedenle güvende olmak için önce anahtarları aşağıdaki gibi bir paketle sıralayabilirsiniz: https://www.npmjs.com/package/sort-keys


Güncel containsbir perf optimizasyonu ile işlevini. Gösterdiğiniz için teşekkürler .


Bu özel kod yığını IE6'da çalışabilir (test edilmemiştir), ancak IE9'a kadar IE ES5'i desteklemedi.
Mark Reed

Performans nedenlerinden dolayı dizgiden kaçınmalısınız. En azından JSON.stringify her döngüde "obj" çünkü pahalı ve uygulamayı yavaşlatacaktır kaçınmalısınız. Bu nedenle, geçici bir değişkende for-
loop'tan

1
@itinance iyi bir nokta. Güncelleme includesÖneriniz ile işlevini. Ben fonksiyonu ile jsperf koştum. Lodash'ın içerdiğinden yaklaşık 5 kat daha yavaş. Lodash değeriyle karşılaştırmak değildir ve bulamıyorum rağmen {a: 1}içinde [{a: 1}]. Herhangi bir kütüphanenin bunu yapıp yapmadığını bilmiyorum. Ama bunu yapmak için daha performanslı ve inanılmaz derecede karmaşık bir yol olup olmadığını merak ediyorum.
Igor Barbashin

Geç not: contains([{ a: 1, b: 2 }], { b: 2, a: 1 })dize edilmiş nesnelerin özelliklerin sırasını koruduğu için , bununla çalışmaz .
Heretic Maymun

1
@HereticMonkey, doğru. Bu yüzden sort-keysnotu en alta
ekledim

12

Lodash'ın bazı işlevlerini kullanın .

Kısa, doğru ve mükemmel bir çapraz platform desteğine sahip.

Kabul edilen cevap şartları bile karşılamıyor.

Gereksinimler: Bir JavaScript dizisinin bir nesne içerip içermediğini öğrenmek için en özlü ve etkili yolu önerin.

Kabul edilen cevap:

$.inArray({'b': 2}, [{'a': 1}, {'b': 2}])
> -1

Benim tavsiyem:

_.some([{'a': 1}, {'b': 2}], {'b': 2})
> true

Notlar:

$ .inArray , bir dizi skalerde skaler değerin var olup olmadığını belirlemek için iyi çalışır ...

$.inArray(2, [1,2])
> 1

... ancak soru, bir nesnenin bir dizide bulunup bulunmadığını belirlemenin etkili bir yolunu ister .

Hem skaler hem de nesneleri işlemek için şunları yapabilirsiniz:

(_.isObject(item)) ? _.some(ary, item) : (_.indexOf(ary, item) > -1)

10

ECMAScript 6, şık bir teklif sunuyor.

Find yöntemi, geri çağrının gerçek bir değer döndürdüğü bir tanesini bulana kadar dizide bulunan her öğe için geri arama işlevini bir kez yürütür. Böyle bir eleman bulunursa find hemen o elemanın değerini döndürür. Aksi takdirde, tanımsızları döndürür. geri arama yalnızca atanmış değerleri olan dizinin dizinleri için çağrılır; silinmiş veya hiç değer atanmamış dizinler için çağrılmaz.

İşte bununla ilgili MDN belgeleri .

Bulma işlevi şu şekilde çalışır.

function isPrime(element, index, array) {
    var start = 2;
    while (start <= Math.sqrt(element)) {
        if (element % start++ < 1) return false;
    }
    return (element > 1);
}

console.log( [4, 6, 8, 12].find(isPrime) ); // Undefined, not found
console.log( [4, 5, 8, 12].find(isPrime) ); // 5

Bunu işlevi tanımlayarak ECMAScript 5 ve önceki sürümlerde kullanabilirsiniz .

if (!Array.prototype.find) {
  Object.defineProperty(Array.prototype, 'find', {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(predicate) {
      if (this == null) {
        throw new TypeError('Array.prototype.find called on null or undefined');
      }
      if (typeof predicate !== 'function') {
        throw new TypeError('predicate must be a function');
      }
      var list = Object(this);
      var length = list.length >>> 0;
      var thisArg = arguments[1];
      var value;

      for (var i = 0; i < length; i++) {
        if (i in list) {
          value = list[i];
          if (predicate.call(thisArg, value, i, list)) {
            return value;
          }
        }
      }
      return undefined;
    }
  });
}


9

Bunu array.indexOf(x)!=-1yapmanın en özlü yolu (ve on yıldan fazla bir süredir Internet Explorer olmayan tarayıcılar tarafından destekleniyor ...) olsa da, O (1) değil, daha çok O (N). Diziniz değişmezse, dizinizi bir hashtable biçimine dönüştürebilir table[x]!==undefinedveya şunu yapabilirsiniz ===undefined:

Array.prototype.toTable = function() {
    var t = {};
    this.forEach(function(x){t[x]=true});
    return t;
}

Demo:

var toRemove = [2,4].toTable();
[1,2,3,4,5].filter(function(x){return toRemove[x]===undefined})

(Ne yazık ki, bir diziyi "dondurmak" ve bir hashtable'ı iki satırda this._cache içinde saklamak için bir Array.prototype.contain oluşturabilirsiniz, ancak dizinizi daha sonra düzenlemeyi seçerseniz bu yanlış sonuçlar verir. örneğin Python'dan farklı olarak bu durumu korumanıza izin verin.)


9

"Has ()" yöntemine sahip Set kullanılabilir :

function contains(arr, obj) {
      var proxy = new Set(arr);
      if (proxy.has(obj))
        return true;
      else
        return false;
    }

    var arr = ['Happy', 'New', 'Year'];
    console.log(contains(arr, 'Happy'));


5
Bence return proxy.has(obj)iki satır daha temiz if-else deyimi burada birlikte
Maciej Bukowski

function contains(arr, obj) { return new Set(arr).has(obj); }
Gordon Bean

8

kullanın:

var myArray = ['yellow', 'orange', 'red'] ;

alert(!!~myArray.indexOf('red')); //true

gösteri

tilde ~Bu noktada ne yapacağını tam olarak bilmek için bu soruya bakın Bir tilde bir ifadeden önce geldiğinde ne yapar? .


5
Bu yıl yayınlandı ve yarım yıl önce tekrar etmeye gerek yok.
Gölge Sihirbazı Senin için Kulak

3
Aslında yayınlanmadı. Bir cevap olarak değil, bir cevabın yorumu olarak ve o zaman bile net ve özlü değil. Gönderdiğiniz için teşekkürler, Mina Gabriel.
T.CK

6

Tamam, sadece sonucu elde etmek için kodunuzu optimize edebilirsiniz !

Bunu daha temiz ve daha iyi yapmanın birçok yolu var, ancak sadece deseninizi almak ve bunu kullanarak uygulamak istedim JSON.stringify, sadece durumunuzda böyle bir şey yapın:

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

Geç not: contains([{ a: 1, b: 2 }], { b: 2, a: 1 })dize edilmiş nesnelerin özelliklerin sırasını koruduğu için , bununla çalışmaz .
Heretic Monkey

5

Hiçbir şekilde en iyisi değil, ama sadece yaratıcı oluyordum ve repertuarım ekliyordum.

Bunu kullanma

Object.defineProperty(Array.prototype, 'exists', {
  value: function(element, index) {

    var index = index || 0

    return index === this.length ? -1 : this[index] === element ? index : this.exists(element, ++index)
  }
})


// Outputs 1
console.log(['one', 'two'].exists('two'));

// Outputs -1
console.log(['one', 'two'].exists('three'));

console.log(['one', 'two', 'three', 'four'].exists('four'));


Bu değilse ne kullanmalısınız?
bryc

@bryc belki kabul edilen çözüm veya buradan başka bir çözüm. Performans için fazla umursamıyorsanız, bunu kullanabileceğinizden
sqram

5

Bu sorunun hala 2 sent ekleyerek en son sözdiziminin eklenmemiş olması şaşırtıcıydı.

Diyelim ki arrObj Nesneleri dizimiz var ve içinde obj aramak istiyoruz.

Array.prototype. indexOf -> ( dizini veya -1 değerini döndürür ) genellikle dizideki öğenin dizinini bulmak için kullanılır. Bu, nesne aramak için de kullanılabilir, ancak yalnızca aynı nesneye başvuru iletiyorsanız çalışır.

let obj = { name: 'Sumer', age: 36 };
let arrObj = [obj, { name: 'Kishor', age: 46 }, { name: 'Rupen', age: 26 }];


console.log(arrObj.indexOf(obj));// 0
console.log(arrObj.indexOf({ name: 'Sumer', age: 36 })); //-1

console.log([1, 3, 5, 2].indexOf(2)); //3

Array.prototype. içerir -> ( doğru veya yanlış döndürür )

console.log(arrObj.includes(obj));  //true
console.log(arrObj.includes({ name: 'Sumer', age: 36 })); //false

console.log([1, 3, 5, 2].includes(2)); //true

Array.prototype. find -> (geri arama alır, CB'de true değerini döndüren ilk değeri / nesneyi döndürür).

console.log(arrObj.find(e => e.age > 40));  //{ name: 'Kishor', age: 46 }
console.log(arrObj.find(e => e.age > 40)); //{ name: 'Kishor', age: 46 }

console.log([1, 3, 5, 2].find(e => e > 2)); //3

Array.prototype. findIndex -> (geri çağrıyı alır, CB'de true değerini döndüren ilk değerin / nesnenin dizinini döndürür).

console.log(arrObj.findIndex(e => e.age > 40));  //1
console.log(arrObj.findIndex(e => e.age > 40)); //1

console.log([1, 3, 5, 2].findIndex(e => e > 2)); //1

Find ve findIndex bir geri arama aldığından, gerçek koşulu yaratıcı bir şekilde ayarlayarak diziden herhangi bir nesneyi (referansımız olmasa bile) alabiliriz.


5

Bu gereksinim için basit çözüm kullanıyor find()

Aşağıdaki gibi bir dizi nesneniz varsa,

var users = [{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "admin"},
{id: "105", name: "user"}];

Ardından, değeriniz olan nesnenin zaten mevcut olup olmadığını kontrol edebilirsiniz.

let data = users.find(object => object['id'] === '104');

veriler null ise yönetici yoksa, aksi takdirde aşağıdaki gibi mevcut nesneyi döndürür.

{id: "104", name: "admin"}

Sonra dizide bu nesnenin dizinini bulabilir ve aşağıdaki kodu kullanarak nesneyi değiştirebilirsiniz.

let indexToUpdate = users.indexOf(data);
let newObject = {id: "104", name: "customer"};
users[indexToUpdate] = newObject;//your new object
console.log(users);

aşağıdaki gibi değer alacaksınız

[{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "customer"},
{id: "105", name: "user"}];

Umarım bu herkese yardımcı olur.


5

    function countArray(originalArray) {
     
    	var compressed = [];
    	// make a copy of the input array
    	var copyArray = originalArray.slice(0);
     
    	// first loop goes over every element
    	for (var i = 0; i < originalArray.length; i++) {
     
    		var count = 0;	
    		// loop over every element in the copy and see if it's the same
    		for (var w = 0; w < copyArray.length; w++) {
    			if (originalArray[i] == copyArray[w]) {
    				// increase amount of times duplicate is found
    				count++;
    				// sets item to undefined
    				delete copyArray[w];
    			}
    		}
     
    		if (count > 0) {
    			var a = new Object();
    			a.value = originalArray[i];
    			a.count = count;
    			compressed.push(a);
    		}
    	}
     
    	return compressed;
    };
    
    // It should go something like this:
    
    var testArray = new Array("dog", "dog", "cat", "buffalo", "wolf", "cat", "tiger", "cat");
    var newArray = countArray(testArray);
    console.log(newArray);

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.