Array.push()如果不存在?

如果两个值都不存在,我如何推入数组?这是我的数组:

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

如果我试图用name: "tom"text: "tasty"再次推入数组,我不希望发生任何事情…但如果这两个都不存在,则我希望它.push()

我该怎么做呢?

569429 次浏览

你可以用一个自定义方法扩展Array原型:

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

http://api.jquery.com/jQuery.unique/ < a href = " http://api.jquery.com/jQuery.unique/ " > < / >

var cleanArray = $.unique(clutteredArray);

你可能对makeArray也感兴趣

前面的例子最好说明在push之前检查它是否存在。 事后看来,它还声明你可以将它声明为原型的一部分(我猜这是又名类扩展),所以下面没有大的增强

除了我不确定indexOf是一个更快的路径,然后inArray?可能。

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

如果没有结果,可以使用jQuery grep和push: http://api.jquery.com/jQuery.grep/

这基本上是与“扩展原型”解决方案相同的解决方案,但没有扩展(或污染)原型。

正是出于这些原因,使用underscore.js这样的js库。union:计算传入数组的并集:在一个或多个数组中出现的唯一项的列表。

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

如果有人有不太复杂的要求,这里是我对一个简单字符串数组的答案的改编:

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

更新:替换indexOf和trim与jQuery的IE8兼容性的替代品

如果你需要一些简单的东西,而不想扩展数组原型:

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

对于字符串数组(但不是对象数组),你可以通过调用.indexOf()来检查项是否存在,如果不存在,则只需将项放入数组:

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)

使用Array.findIndex函数很容易做到,它接受一个函数作为参数:

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


index === -1 ? arrayObj.push({your_object}) : console.log("object already exists")
 

您可以使用foreach检查数组,然后弹出项目,如果它存在,否则添加新的项目…

submitFields是键值对

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

当你希望通过对象的特定属性进行搜索时,我使用了map和reduce来做到这一点,因为直接进行对象相等通常会失败。

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");
}

可以使用带有回调函数及其"this"参数的findIndex方法。

注意:旧的浏览器不知道findIndex,但是一个polyfill是可用的。

示例代码(注意,在原始问题中,只有当一个新对象的数据都不在之前的推送对象中时,它才会被推送):

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

像这样的吗?

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

与对象

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

我知道这是一个非常老的问题,但如果你使用ES6,你可以使用一个非常小的版本:

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

非常简单,首先添加一个过滤器,删除项目-如果它已经存在,然后通过concat添加它。

下面是一个更现实的例子:

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


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

如果你的数组包含对象,你可以像这样调整过滤器函数:

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

这是一个比较对象的函数。在某些情况下,您可能需要比较许多字段。 只需循环数组,并使用现有项和新项调用此函数

 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;
};

不确定速度,但stringification + indexOf是一个简单的方法。首先将数组转换为字符串:

let strMyArray = JSON.stringify(myArray);

然后,对于一系列属性-值对,您可以使用:

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

查找整个对象更简单:

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

短的例子:

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

推动动态

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);

用简单的方法

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

如果数组只包含基元类型/简单数组

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

我建议你使用

集只允许唯一的条目,这将自动解决您的问题。

集合可以这样声明:

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

我想我在这里回答太迟了,然而这是我最终想出的一个邮件管理器我写。好的,这就是我需要的。

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>

A是你拥有的对象数组

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

简单的代码,如果'indexOf'返回'-1',这意味着元素不在数组中,那么条件'=== -1'检索true/false。

'&&'操作符的意思是'and',所以如果第一个条件为真,我们将它推入数组。

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

这里你有一种方法可以在一行中为两个数组做这件事:

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]
someArray = [{a: 'a1 value', b: {c: "c1 value"},
{a: 'a2 value', b: {c: "c2 value"}]
newObject = {a: 'a2 value', b: {c: "c2 value"}}


//New object which needs check for duplicity


let isExists = checkForExists(newObject) {
return someArray.some(function(el) {
return el.a === newObject.a && el.b.c === newObject.b.c;
});
}
// write your logic here
// if isExists is true then already object in an array else you can add

推送后删除重复项

如果你已经有一个包含重复项的数组,将对象数组转换为字符串数组,然后使用Set()函数消除重复项:

let arr_obj = [
{ name: "tom", text: "tasty" },
{ name: "tom", text: "tasty" }
]


let arr_str = arr_obj.map(JSON.stringify)


let arr_unique = [...new Set(arr_str)].map(JSON.parse)

推前检查

如果你到目前为止没有重复的元素,你想在推入一个新元素之前检查重复:

let arr_obj = [
{ name: "tom", text: "tasty" },
{ name: "tim", text: "tusty" }
]


let new_obj = { name: "tom", text: "tasty" }


let arr_str = arr_obj.map(JSON.stringify)


!arr_str.includes(JSON.stringify(new_obj)) && arr_obj.push(new_obj)

我的选择是使用.includes()扩展数组。正如@Darrin Dimitrov所建议的原型:

Array.prototype.pushIfNotIncluded = function (element) {
if (!this.includes(element)) {
this.push(element);
}
}
只要记住includes来自es6,在IE上不起作用: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes < / p >

这个问题有点老了,但我的选择是

    let finalTab = [{id: 1, name: 'dupont'}, {id: 2, name: 'tintin'}, {id: 3, name:'toto'}]; // Your array of object you want to populate with distinct data
const tabToCompare = [{id: 1, name: 'dupont'}, {id: 4, name: 'tata'}]; // A array with 1 new data and 1 is contain into finalTab
    

finalTab.push(
...tabToCompare.filter(
tabToC => !finalTab.find(
finalT => finalT.id === tabToC.id)
)
); // Just filter the first array, and check if data into tabToCompare is not into finalTab, finally push the result of the filters


console.log(finalTab); // Output : [{id: 1, name: 'dupont'}, {id: 2, name: 'tintin'}, {id: 3, name: 'toto'}, {id: 4, name: 'tata'}];

我有这个问题,我做了一个简单的原型,使用它,如果你喜欢它

Array.prototype.findOrPush = function(predicate, fallbackVal) {
let item = this.find(predicate)
if(!item){
item = fallbackVal
this.push(item)
}
return item
}


let arr = [{id: 1}]
let item = arr.findOrPush(e => e.id == 2, {id: 2})
console.log(item) // {id: 2}


// will not push and just return existing value
arr.findOrPush(e => e.id == 2, {id: 2})
conslog.log(arr)  // [{id: 1}, {id: 2}]


我更喜欢使用本机js Array.prototype.some(),即使在jQ env
文档:w3 some or mdn some

let arr = [
{ name: "tom", text: "tasty" },
{ name: "tom", text: "tasty" }
];
let oneMore = { name: "tom", text: "tasty" };
!arr.some(i => i.name == oneMore.name && i.text == oneMore.text)
&& arr.push(oneMore);

如果你的项目包含lodash,使用unionBy方法会很简单

import {unionBy} from "lodash";


let arrayObj = [
{ name: "jhon", text: "guitar"},
{ name: "paul", text: "bass" },
{ name: "george", text: "guitar" }
];


// this object will be added to the array
arrayObj = unionBy(arrayObj, [{name: 'ringo', text: 'drums'}], 'name')


// this object will be ignored because already exists
arrayObj = unionBy(arrayObj, [{name: "jhon", text: "guitar"}], 'name')