335

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

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

name: "tom"如果我尝试使用or再次推入数组text: "tasty",我不希望发生任何事情......但如果这些都不存在,那么我希望它.push()

我怎样才能做到这一点?

4

28 回答 28

552

For an array of strings (but not an array of objects), you can check if an item exists by calling .indexOf() and if it doesn't then just push the item into the array:

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)

于 2016-04-17T23:32:40.757 回答
171

使用函数很容易做到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")
 
于 2016-06-09T13:16:32.713 回答
127

您可以使用自定义方法扩展 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; 
});
于 2010-01-01T11:12:31.320 回答
43

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;
}
于 2012-10-13T23:02:08.320 回答
33

像这样?

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)
于 2017-03-04T17:35:26.597 回答
31

我知道这是一个非常古老的问题,但如果你使用的是 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 }])
于 2017-04-24T14:28:49.087 回答
30

动态推送

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);
于 2019-02-07T13:53:03.963 回答
26

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

_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2, 3, 101, 10]
于 2014-06-02T18:39:02.497 回答
24

简单的代码,如果“indexOf”返回“-1”,则表示该元素不在数组内,则条件“=== -1”检索真/假。

'&&' 运算符的意思是 'and',所以如果第一个条件为真,我们将其推送到数组中。

array.indexOf(newItem) === -1 && array.push(newItem);
于 2020-01-08T08:07:59.630 回答
18

我建议你使用Set

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

集合可以这样声明:

const baz = new Set(["Foo","Bar"])
于 2019-04-23T22:49:29.927 回答
8

我的选择是.includes()按照@Darrin Dimitrov 的建议使用扩展 Array.prototype:

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

于 2021-01-19T16:02:22.110 回答
4

不确定速度,但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);
}
于 2017-11-20T02:32:01.197 回答
3

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

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

更新:用 jQuery 替代品替换 indexOf 和 trim 以实现 IE8 兼容性

于 2015-03-25T17:16:33.340 回答
3

如果您需要一些简单的东西而不想扩展 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);
}
于 2016-01-15T06:37:27.220 回答
2

您可以将 findIndex 方法与回调函数及其“this”参数一起使用。

注意:旧浏览器不知道 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
于 2016-11-07T14:40:29.650 回答
2

推送后删除重复项

如果您已经有一个包含重复项的数组,请将对象数组转换为字符串数组,然后使用该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)
于 2020-10-27T10:15:04.793 回答
2

在您希望通过对象的特定属性进行搜索的情况下,我使用 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");
}
于 2016-08-23T17:51:35.693 回答
2

我想我在这里回答为时已晚,但这是我最终为我写的邮件管理器想出的。作品这就是我所需要的。

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>

于 2019-07-01T08:22:01.120 回答
2

a 是您拥有的对象数组

a.findIndex(x => x.property=="WhateverPropertyYouWantToMatch") <0 ? 
a.push(objectYouWantToPush) : console.log("response if object exists");
于 2019-10-12T14:04:35.600 回答
1

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

    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'}];
于 2021-06-25T08:07:38.477 回答
1

Array.prototype.some()即使在 jQ env
Docs中,我也更愿意使用本机 js : w3ssomemdnsome

let arr = [
    { name: "tom", text: "tasty" },
    { name: "tom", text: "tasty" },
    { name: "tom", text: "tasty" },
    { 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);
于 2022-02-04T22:07:06.767 回答
1

在这里,您有一种方法可以在一行中为两个数组执行此操作:

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]
于 2020-03-29T15:48:29.007 回答
0

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

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

于 2021-10-13T17:50:55.860 回答
0

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

 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;
    };
于 2017-05-18T05:11:34.600 回答
0
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
于 2020-07-09T08:14:30.467 回答
0

简短的例子:

if (typeof(arr[key]) === "undefined") {
  arr.push(key);
}
于 2018-07-26T16:59:26.390 回答
-2

如果没有结果,您可以使用 jQuery grep 并推送:http: //api.jquery.com/jQuery.grep/

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

于 2013-07-24T12:59:56.223 回答
-2

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

示例 newItemValue &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});
于 2016-07-13T17:01:09.687 回答