簡體   English   中英

Array.push() 如果不存在?

[英]Array.push() if does not exist?

如果兩個值都不存在,我如何才能推入數組? 這是我的數組:

[
    { 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()

我怎樣才能做到這一點?

對於字符串數組(但不是對象數組),您可以通過調用.indexOf()來檢查項目是否存在,如果不存在, .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")
 

您可以使用自定義方法擴展 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/

var cleanArray = $.unique(clutteredArray);

你可能也對 makeArray 感興趣

前面的例子最好說在推送之前檢查它是否存在。 事后看來,它還指出您可以將其聲明為原型的一部分(我想這就是類擴展),因此下面沒有大的增強。

除了我不確定 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;
}

像這樣?

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

正是出於這些原因,使用像underscore.js這樣的 js 庫。 使用: union:計算傳入數組的並集:一個或多個數組中按順序排列的唯一項的列表。

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

簡單的代碼,如果 'indexOf' 返回 '-1',則表示該元素不在數組內,則條件 '=== -1' 檢索真/假。

'&&' 運算符的意思是 'and',所以如果第一個條件為真,我們將它推送到數組中。

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

我建議你使用Set

集合只允許唯一的條目,這會自動解決您的問題。

集合可以這樣聲明:

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

不確定速度,但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);
}

我的選擇是使用.includes()擴展 Array.prototype 作為@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

如果有人有不太復雜的要求,這里是我對簡單字符串數組的答案的改編:

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 兼容性

如果您需要一些簡單的東西而不想擴展 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);
}

在您希望通過對象的特定屬性進行搜索的情況下,我使用 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");
}

您可以將 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

我想我在這里回答為時已晚,但這就是我最終為我寫的郵件管理器想到的。 工作這就是我所需要的。

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

簡短示例:

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

在這里,您有一種方法可以在一行中為兩個數組執行此操作:

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]

推送后刪除重復項

如果您已經有一個包含重復項的數組,請將對象數組轉換為字符串數組,然后使用Set()函數消除重復項:

// Declaring an array of objects containing duplicate objects
let arrayOfObjects = [{name: "tom", text: "tasty"}, {name: "tom", text: "tasty"}];

// Transforming array of objects into array of strings
let arrayOfStrings = arrayOfObjects.map(obj => JSON.stringify(obj));

// Creating a new set, Set() returns unique values by definition
let uniqueSet = new Set(arrayOfStrings);

// Transforming set into array and reversing strings to objects
let uniqueArrayOfObjects = [...uniqueSet].map(elem => JSON.parse(elem));

console.log(uniqueArrayOfObjects);
// [{name: "tom", text: "tasty"}]

推前檢查

如果到目前為止您沒有重復項並且您想在推送新元素之前檢查重復項:

// Declaring an array of objects without duplicates
let arrayOfObjects = [{name: "tom", text: "tasty"}];

// Transforming array of objects into array of strings
let arrayOfStrings = arrayOfObjects.map(obj => JSON.stringify(obj));

// Declaring new element as an example
let newElem = {name: "tom", text: "tasty"};

// Stringifying new element
let newElemString = JSON.stringify(newElem);

// At this point, check if the string is duplicated and add it to array
!arrayOfStrings.includes(newElemString) && arrayOfObjects.push(newElem);

console.log(arrayOfObjects);
// [{name: "tom", text: "tasty"}]

這是用於對象比較的工作函數。 在某些情況下,您可能需要比較很多字段。 只需循環數組並使用現有項目和新項目調用此函數。

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

這個問題有點老了,但我的選擇是:

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

即使在 jQ env 中,我也更願意使用本機 js Array.prototype.some()
文檔: w3s somemdn some

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

如果您的項目包含負載,則使用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')

如果不在列表中則添加

對於簡單值的列表,它是一個單行......

[...new Set([...someArray, someElement])]

JavaScript 用法:

var myArray = ['bill','bob']
var alreadyIn = [...new Set([...myArray, 'bob'])] // ['bill','bob']
var notAlreadyIn = [...new Set([...myArray, 'peter'])] // ['bill','bob','peter']

TypeScript 分機(注意包括包括):

interface Array<T> {
  include(element: T): Array<T>
}
Array.prototype.include = function (element: any): any[] {
  return [...new Set([...this, obj])]
}

...但對於對象,它更復雜

[...new Set([...someArray.map((o) => JSON.stringify(o)),
    JSON.stringify(someElement)]).map((o) => JSON.parse(o))

TypeScript ext 處理任何事情:

Array.prototype.include = function (element: any): any[] {
  if (element && typeof element === 'object')
    return [
      ...new Set([
        ...this.map((o) => JSON.stringify(o)),
        JSON.stringify(element),
      ]),
    ].map((o) => JSON.parse(o))
  else return [...new Set([...this, element])]
}

如果沒有結果,您可以使用 jQuery grep 並推送: http : //api.jquery.com/jQuery.grep/

它與“擴展原型”解決方案中的解決方案基本相同,但沒有擴展(或污染)原型。

您可以使用 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});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM