Array.push () yoksa?


247

Her iki değer de yoksa bir diziye nasıl girebilirim? İşte benim dizi:

[
    { name: "tom", text: "tasty" },
    { name: "tom", text: "tasty" },
    { name: "tom", text: "tasty" },
    { name: "tom", text: "tasty" },
    { name: "tom", text: "tasty" }
]

Eğer ya name: "tom"da ile diziye tekrar itmeye çalışırsam text: "tasty", bir şey olmasını istemiyorum ... ama bunların hiçbiri orada değilse.push()

Bunu nasıl yapabilirim?


5
Dizi yerine sözlük (karma / ağaç) kullanın.
Thomas Eding

Bütün bunlar javascriptte mevcut mu?
rahul


3
bir Set
Drax

1
Set bir dizi nesne ile çalışmaz
rffaguiar

Yanıtlar:


114

Array prototipini özel bir yöntemle genişletebilirsiniz:

// check if an element exists in array using a comparer function
// comparer : function(currentElement)
Array.prototype.inArray = function(comparer) { 
    for(var i=0; i < this.length; i++) { 
        if(comparer(this[i])) return true; 
    }
    return false; 
}; 

// adds an element to the array if it does not already exist using a comparer 
// function
Array.prototype.pushIfNotExist = function(element, comparer) { 
    if (!this.inArray(comparer)) {
        this.push(element);
    }
}; 

var array = [{ name: "tom", text: "tasty" }];
var element = { name: "tom", text: "tasty" };
array.pushIfNotExist(element, function(e) { 
    return e.name === element.name && e.text === element.text; 
});

5
Kampçı (karşılaştırıcı?) İki argüman alması gerektiğini düşünüyorum, bu katma değer satır içi ve fonksiyonunuzda erişebileceğiniz bir değişken değil durumda basitleştirir. array.pushIfNotExist ({ad: "tom", metin: "lezzetli"}, işlev (a, b) {dönüş a.name === b.name && a.text === b.text;});
Vincent Robert

26
Bunun neden dile özgü olmadığını merak ediyorum - nasıl uygulandığını unutun - 'yalnızca benzersiz olması durumunda ekleme' fikri var olduğu varsayıldığı kadar temeldir.
justSteve

9
Array prototipini inArray yerine JavaScript 1.6 yöntemi IndexOf ile genişletmek daha iyidir.
Eugene Gluhotorenko

7
Array.findIndex()kodunuzla aynı olan yerleşik bir JS işlevidir.

4
Yerleşik nesneleri doğrudan genişletmek kötü bir uygulamadır.
Slava Fomin II

429

Bir öğe arayarak varsa dizeleri dizisi (ancak nesnelerin dizisi) için, kontrol edebilir .indexOf()ve bunları yapmazsa o zaman sadece itme diziye öğe:

var newItem = "NEW_ITEM_TO_ARRAY";
var array = ["OLD_ITEM_1", "OLD_ITEM_2"];

array.indexOf(newItem) === -1 ? array.push(newItem) : console.log("This item already exists");

console.log(array)


50
Bunun neden doğru olarak işaretlenmediğinden emin değilim. Herhangi bir harici cihaz kullanmaz, bir uzantı oluşturmayı gerektirmez ve çok basittir. Operasyon sorusu için mükemmel cevap.
pimbrouwers

39
İlk soruda, dizinin değerleri dizeler değil nesnelerdir (ve bu çözüm değerler nesneler gibi çalışmaz).
Simon Hi

12
@EmilPedersen - pek değil. if (a.indexOf({ name: "tom", text: "tasty" })!=-1) a.push({ name: "tom", text: "tasty" })İki kez deneyin . İki kez 'benzer' bir nesne ekleyecektir.
commonpike

18
Bu cevap nesnel olarak yanlış olduğu için kaldırılmalı, ancak yine de en fazla sayıda oyu çekti.
nikola

2
Bu doğru bir cevap değil, neden kabul ediliyor? Sadece diziler içinde nesne için değil, Js dizileri için çalışır.
digitai

100

Array.findIndexBir işlevi bağımsız değişken olarak alan işlevi kullanarak yapmak oldukça kolaydır :

var a = [{name:"bull", text: "sour"},
    { name: "tom", text: "tasty" },
    { name: "tom", text: "tasty" }
]
var index = a.findIndex(x => x.name=="bob")
// here you can check specific property for an object whether it exist in your array or not

if (index === -1){
    a.push({your_object});
}
else console.log("object already exists")

8
BU cevap çocuklar!
jafed

2
mevcut değilse diziye bir öğe eklemek için en alakalı
akshay bagade

1
Teşekkürler, her yerde bunu arıyordu.
dt192

41

http://api.jquery.com/jQuery.unique/

var cleanArray = $.unique(clutteredArray);

siz de makeArray ilginizi çekebilir

Önceki örnek, itmeden önce var olup olmadığını kontrol etmenin en iyi örneğidir. Görüyorum ki, bunu da prototipin bir parçası olarak ilan edebileceğinizi belirtiyor (sanırım bu Sınıf Uzantısı), bu yüzden aşağıda büyük bir gelişme yok.

Dışında indexOf daha hızlı bir rota olduğundan emin değilim inArray? muhtemelen.

Array.prototype.pushUnique = function (item){
    if(this.indexOf(item) == -1) {
    //if(jQuery.inArray(item, this) == -1) {
        this.push(item);
        return true;
    }
    return false;
}

22
JQuery bağlantısından: Note that this only works on arrays of DOM elements, not strings or numbers.Ayrıca, indexOf
IE8'de

IE8
LTroya

25

Bu nedenlerle tam olarak underscore.js gibi bir js kütüphanesi kullanın . Kullanım: birleşim: Aktarılan dizilerin birleşimini hesaplar: sırasıyla, dizilerden bir veya daha fazlasında bulunan benzersiz öğelerin listesi.

_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2, 3, 101, 10]

8
Bunun yeni bir dizi döndürdüğünü ve mevcut bir diziye gerçekten aktarılmadığını unutmayın.
ilovett

4
IMHO gerçekten bu kadar basit bir şeye karşı test etmek için bir çerçeve getirmeye gerek yok
DrewT

24

Bunun gibi?

var item = "Hello World";
var array = [];
if (array.indexOf(item) === -1) array.push(item);

Nesne ile

var item = {name: "tom", text: "tasty"}
var array = [{}]
if (!array.find(o => o.name === 'tom' && o.text === 'tasty'))
    array.push(item)

4
array.finddizi için arama yaptığı için kötü bir fikirdir. findIndexYalnızca ilk gerçekleşene kadar arama yapan kullanımı .

3
@ Buna göre K48: stackoverflow.com/a/33759573/5227365 öğeyi bulduktan sonra "bul" durur
Pascal

19

Bunun çok eski bir soru olduğunu biliyorum, ancak ES6 kullanıyorsanız çok küçük bir sürüm kullanabilirsiniz:

[1,2,3].filter(f => f !== 3).concat([3])

Çok kolay, önce öğeyi kaldıran bir filtre ekleyin - zaten varsa ve ardından bir concat ile ekleyin.

İşte daha gerçekçi bir örnek:

const myArray = ['hello', 'world']
const newArrayItem

myArray.filter(f => f !== newArrayItem).concat([newArrayItem])

Diziniz nesneler içeriyorsa, filtre işlevini şu şekilde uyarlayabilirsiniz:

someArray.filter(f => f.some(s => s.id === myId)).concat([{ id: myId }])

3
Burada oldukça zarif bir çözüm. Teşekkürler!
Jonathan Picazo

18

Dinamik olarak itin

var a = [
  {name:"bull", text: "sour"},
  {name: "tom", text: "tasty" },
  {name: "Jerry", text: "tasty" }
]

function addItem(item) {
  var index = a.findIndex(x => x.name == item.name)
  if (index === -1) {
    a.push(item);
  }else {
    console.log("object already exists")
  }
}

var item = {name:"bull", text: "sour"};
addItem(item);

Basit yöntemle

var item = {name:"bull", text: "sour"};
a.findIndex(x => x.name == item.name) == -1 ? a.push(item) : console.log("object already exists")

Dizi yalnızca ilkel türler / basit dizi içeriyorsa

var b = [1, 7, 8, 4, 3];
var newItem = 6;
b.indexOf(newItem) === -1 && b.push(newItem);

2
Basit ve güzel bir çözüm @Gopala raja naika
Nasimba

11

Bir Set kullanmanızı öneririm ,

Yalnızca sorununuzu otomatik olarak çözen benzersiz girişlere izin verir.

Setler şöyle beyan edilebilir:

const baz = new Set(["Foo","Bar"])

@Michael'i işaret ettiğin için teşekkürler. Asgari çabayla farklı verileri korumak istediğimiz zamanlar için iyi bir çözüm. FWIW, dizi performansının daha iyi olduğunu, çünkü gerektiğinde öğeyi getirmek için daha az CPU gerektirdiğini belirtmek önemlidir.
Ben

Soru sorar Array.pushböylece, Set.addo eşdeğerdir.
bryc

9

Kolay kod, 'indexOf' '-1' döndürürse, öğenin dizinin içinde olmadığı anlamına gelir, ardından '=== -1' koşulu true / false değerini alır.

'&&' operatörü 've' anlamına gelir, bu nedenle ilk koşul doğruysa diziye iteriz.

array.indexOf(newItem) === -1 && array.push(newItem);

@ D.Lawrence Evet, şimdi çok daha iyi.
Eric Valero

OP'nin sorusunu sağlayan kabul edilmiş başka cevaplar da var ve bunlar bir süre önce yayınlandı. Bir cevap gönderirken bkz: İyi bir cevabı nasıl yazarım? , özellikle eski soruları yanıtlarken yeni bir çözüm veya çok daha iyi bir açıklama eklediğinizden emin olun.
help-info.de

4

Hız konusunda emin değilim, ama stringification+ indexOfbasit bir yaklaşımdır. Dizinizi bir dizeye dönüştürerek başlayın:

let strMyArray = JSON.stringify(myArray);

Ardından bir dizi özellik değeri çifti için şunları kullanabilirsiniz:

if (strMyArray.indexOf('"name":"tom"') === -1 && strMyArray.indexOf('"text":"tasty"') === -1) {
   myArray.push({ name: "tom", text: "tasty" });
}

Bütün bir nesneyi bulmak daha kolaydır:

if (strMyArray.indexOf(JSON.stringify(objAddMe) === -1) { 
   myArray.push(objAddMe);
}

3

Array prototipini genişletmek istemeden basit bir şeye ihtiyacınız varsa:

// Example array
var array = [{id: 1}, {id: 2}, {id: 3}];

function pushIfNew(obj) {
  for (var i = 0; i < array.length; i++) {
    if (array[i].id === obj.id) { // modify whatever property you need
      return;
    }
  }
  array.push(obj);
}

3

Herkesin daha az karmaşık gereksinimleri varsa, basit bir dize dizisi için benim cevap adaptasyon:

Array.prototype.pushIfNotExist = function(val) {
    if (typeof(val) == 'undefined' || val == '') { return; }
    val = $.trim(val);
    if ($.inArray(val, this) == -1) {
        this.push(val);
    }
};

Güncelleme: IE8 uyumluluğu için indexOf ve trim jQuery alternatifleriyle değiştirildi


güzel bir çözüm, ama neden trim kullanıyorsunuz?
Dejan Dozet

2

Bir nesnenin belirli bir özelliğine göre arama yapmak istediğinizde, doğrudan nesne eşitliği yapmak yararlı olduğunda genellikle bunu yapmak ve azaltmak için harita kullandım.

var newItem = {'unique_id': 123};
var searchList = [{'unique_id' : 123}, {'unique_id' : 456}];

hasDuplicate = searchList
   .map(function(e){return e.unique_id== newItem.unique_id})
   .reduce(function(pre, cur) {return pre || cur});

if (hasDuplicate) {
   searchList.push(newItem);
} else {
   console.log("Duplicate Item");
}

2

Kısa bir örnek:

if (typeof(arr[key]) === "undefined") {
  arr.push(key);
}

1
Doğru değil. Anahtarı itmekle ilgilenmiyoruz, bir isim-değer çiftini itmek istiyoruz, ancak sadece mevcut değilse.
Stefan

2

a sahip olduğunuz nesne dizisidir

a.findIndex(x => x.property=="WhateverPropertyYouWantToMatch") <0 ? 
a.push(objectYouWantToPush) : console.log("response if object exists");

1

FindIndex yöntemini bir geri çağırma işleviyle ve bunun "this" parametresiyle kullanabilirsiniz.

Not: eski tarayıcılar findIndex'i bilmez, ancak çoklu doldurma kullanılabilir.

Örnek kod (orijinal soruda, yeni bir nesnenin yalnızca verilerinin hiçbiri manevra öncesi itilmiş nesnelerde olmadığına dikkat edin):

var a=[{name:"tom", text:"tasty"}], b;
var magic=function(e) {
    return ((e.name == this.name) || (e.text == this.text));
};

b={name:"tom", text:"tasty"};
if (a.findIndex(magic,b) == -1)
    a.push(b); // nothing done
b={name:"tom", text:"ugly"};
if (a.findIndex(magic,b) == -1)
    a.push(b); // nothing done
b={name:"bob", text:"tasty"};
if (a.findIndex(magic,b) == -1)
    a.push(b); // nothing done
b={name:"bob", text:"ugly"};
if (a.findIndex(magic,b) == -1)
    a.push(b); // b is pushed into a

1

Sanırım burada cevaplamak için çok geç, ancak bu nihayet yazdığım bir posta yöneticisi için geldi ne olduğunu. Tüm ihtiyacım olan işler.

window.ListManager = [];
$('#add').click(function(){
//Your Functionality
  let data =Math.floor(Math.random() * 5) + 1 
  
  if (window.ListManager.includes(data)){
      console.log("data exists in list")
  }else{
       window.ListManager.push(data);
  }
  
  
  $('#result').text(window.ListManager);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>Unique List</h1>

<p id="result"></p>
<button id="add">Add to List</button>


0

Bu bir nesne karşılaştırması için çalışma fonk. Bazı durumlarda, karşılaştırılacak çok alanınız olabilir. Diziyi döngüye sokun ve bu işlevi mevcut öğeler ve yeni öğe ile çağırın.

 var objectsEqual = function (object1, object2) {
        if(!object1 || !object2)
            return false;
        var result = true;
        var arrayObj1 = _.keys(object1);
        var currentKey = "";
        for (var i = 0; i < arrayObj1.length; i++) {
            currentKey = arrayObj1[i];
            if (object1[currentKey] !== null && object2[currentKey] !== null)
                if (!_.has(object2, currentKey) ||
                    !_.isEqual(object1[currentKey].toUpperCase(), object2[currentKey].toUpperCase()))
                    return false;
        }
        return result;
    };

0

Burada iki dizi için bir satırda bunu yapmanın bir yolu var:

const startArray = [1,2,3,4]
const newArray = [4,5,6]

const result = [...startArray, ...newArray.filter(a => !startArray.includes(a))]

console.log(result);
//Result: [1,2,3,4,5,6]


-2

Foreach kullanarak diziyi kontrol edebilir ve varsa öğeyi açabilirsiniz, aksi takdirde yeni öğe ekleyebilirsiniz ...

sample newItemValue & sendFields anahtar, değer çiftleridir

> //submitFields existing array
>      angular.forEach(submitFields, function(item) {
>                   index++; //newItemValue new key,value to check
>                     if (newItemValue == item.value) {
>                       submitFields.splice(index-1,1);
>                         
>                     } });

                submitFields.push({"field":field,"value":value});
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.