web-dev-qa-db-fra.com

Array.Push () si n'existe pas?

Comment puis-je pousser dans un tableau si aucune valeur n'existe? Voici mon tableau:

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

Si j'ai essayé d'insérer à nouveau dans le tableau avec name: "tom" ou text: "tasty", je ne veux rien qui se passe ... mais si aucun de ceux-ci ne sont présents, alors je veux que ce soit .Push()

Comment puis-je faire ceci?

176
tarnfeld

Vous pouvez étendre le prototype Array avec une méthode personnalisée:

// 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; 
});
92
Darin Dimitrov

Pour un tableau de chaînes (mais pas un tableau d'objets), vous pouvez vérifier si un élément existe en appelant .indexOf() et si ce n'est pas le cas, alors Push l'élément dans le tableau:

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)

308
Jiří Zahálka

Il est assez facile de faire en utilisant la fonction Array.findIndex, qui prend une fonction en argument:

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")
45
ashish yadav

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

var cleanArray = $.unique(clutteredArray);

makeArray pourrait aussi vous intéresser

L’exemple précédent vaut mieux qu’il vérifie s’il existe avant de pousser . Je vois avec le recul qu’il est également indiqué que vous pouvez le déclarer comme faisant partie du prototype (j’appelle donc Class Extension), donc pas d’amélioration majeure en dessous.

Sauf que je ne suis pas sûr si indexOf est une route plus rapide qu'inArray? Probablement.

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

Utilisez une bibliothèque js telle que underscore.js pour ces raisons exactement. Use: union: calcule l'union des tableaux entrés: la liste des éléments uniques, dans l'ordre, présents dans un ou plusieurs tableaux.

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

Comme ça?

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

Avec objet

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

Je sais que la question est très ancienne, mais si vous utilisez ES6, vous pouvez utiliser une très petite version:

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

Très facile, commencez par ajouter un filtre qui supprime l'élément, s'il existe déjà, puis ajoutez-le via un concat.

Voici un exemple plus réaliste:

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

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

Si votre tableau contient des objets, vous pouvez adapter la fonction de filtrage comme suit:

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

Si vous avez besoin de quelque chose de simple sans vouloir étendre le prototype Array:

// 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
docta_faustus

Pas sûr de la vitesse, mais stringification + indexOf est une approche simple. Commencez par transformer votre tableau en chaîne:

let strMyArray = JSON.stringify(myArray);

Ensuite, pour une série de paires attribut-valeur, vous pouvez utiliser:

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

Trouver un objet entier est plus simple:

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

Au cas où quelqu'un aurait des exigences moins compliquées, voici mon adaptation de la réponse pour un tableau de chaînes simple:

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

Mise à jour: indexOf remplacé et ajustement avec des alternatives jQuery pour la compatibilité avec IE8

2
Scott Beeson

J'ai utilisé mapper et réduire pour le faire dans le cas où vous souhaitez effectuer une recherche en fonction d'une propriété spécifique d'un objet, ce qui est utile car une égalité d'objet directe échoue souvent.

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
Adrian Smith

Vous pouvez utiliser la méthode findIndex avec une fonction de rappel et son paramètre "this".

Remarque: les anciens navigateurs ne connaissent pas findIndex, mais un polyfill est disponible.

Exemple de code (veillez à ce que, dans la question initiale, un nouvel objet ne soit poussé que si aucune de ses données ne se trouve dans des objets déjà poussés):

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
Simon Hi

Je vous suggère d'utiliser un Set ,

Les ensembles ne permettent que des entrées uniques, ce qui résout automatiquement votre problème.

Les ensembles peuvent être déclarés comme suit:

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

Petit exemple:

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

Poussez dynamiquement  

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

addTimelineItem(item) {
  var index = this.initiateTimeline.findIndex(x => x.name == item.name)
  if (index === -1) {
    this.initiateTimeline.Push(item);
  }else {
    console.log("object already exists")
  }
}
0
Raj Gopal

Cela fonctionne pour une comparaison d'objets. Dans certains cas, vous pouvez avoir beaucoup de champs à comparer . Bouclez simplement le tableau et appelez cette fonction avec les éléments existants et les nouveaux.

 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
user3180914

Je suppose que je suis trop tard pour répondre ici, mais c’est ce que j’ai finalement trouvé pour un gestionnaire de courrier que j’ai écrit. Ça marche, c'est tout ce dont j'ai besoin.

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
TheeCodeDragon