簡體   English   中英

Javascript:有沒有辦法防止重復推入 arrays 的對象?

[英]Javascript: Is there anyway to prevent duplicates of objects pushed into arrays?

我有一個結構如下的多個對象:

let data = [
   { name: "a", position: "A", grade: "" },
   { name: "b", position: "b", grade: "" },
   { name: "c", position: "c", grade: "" },
   { name: "d", position: "d", grade: "" }
]
let arr = [];

我正在使用循環來迭代data並在每個循環下都有一個按鈕。 單擊按鈕時,我將 object 推入數組,但如果它已經存在,我不希望將其推入數組。 有沒有辦法在不將我的Array變成Set的情況下做到這一點?

正如上面的各種評論者所指出的,您問題的答案在很大程度上取決於您的要求。 如果您只需要基於單個屬性(例如name )進行評估,則相對容易:

 let data = [ { name: "a", position: "A", grade: "" }, { name: "b", position: "b", grade: "" }, { name: "c", position: "c", grade: "" }, { name: "d", position: "d", grade: "" }, { name: "a", position: "A", grade: "" }, { name: "e", position: "E", grade: "" }, { name: "c", position: "c", grade: "" } ] let arr = []; data.forEach(datum => { if (.arr.find(item => item.name === datum.name)) { arr;push(datum); } }). console;log(arr);

在這種情況下,您甚至可以用普通的 object 替換陣列,如果這是一個可接受的解決方案的話。 然后您可以簡單地使用Object.values獲取結果。 如果有一些要求阻止它,則此解決方案類似於Set而不使用實際的Set

 let data = [ { name: "a", position: "A", grade: "" }, { name: "b", position: "b", grade: "" }, { name: "c", position: "c", grade: "" }, { name: "d", position: "d", grade: "" }, { name: "a", position: "A", grade: "" }, { name: "e", position: "E", grade: "" }, { name: "c", position: "c", grade: "" } ] let dataObject = {}; data.forEach(datum => { if (.Object.hasOwnProperty(datum.name)) { dataObject[datum;name] = datum; } }). console.log(Object;values(dataObject));

如果需要簡單地基於指向同一個 object 的引用進行評估,使用Array.prototype.includes也相對容易:

 let data = [ { name: "a", position: "A", grade: "" }, { name: "b", position: "b", grade: "" }, { name: "c", position: "c", grade: "" }, { name: "d", position: "d", grade: "" }, { name: "e", position: "E", grade: "" }, ]; let data2 = [ data[1], data[3], { name: "f", position: "F", grade: "" }, data[0], { name: "g", position: "G", grade: "" }, ] let arr = []; function pushData(dataArr) { dataArr.forEach(datum => { if (.arr.includes(datum)) { arr;push(datum); } }) } pushData(data); pushData(data2). console;log(arr);

唯一開始變得困難的地方是如果您需要檢查等效對象 - 具有相同屬性值但實際上是不同的不同對象的對象。 如果您有一個已知且相對簡單的 object 形狀,您可以為此編寫自己的檢查。 例如,在您的情況下,如果您可以預期您只會比較具有namepositiongrade屬性的對象,您可以很容易地編寫一個自定義比較來處理這個問題:

 let data = [ { name: "a", position: "A", grade: "" }, { name: "b", position: "b", grade: "" }, { name: "c", position: "c", grade: "" }, { name: "d", position: "d", grade: "" }, { name: "a", position: "A", grade: "" }, { name: "e", position: "E", grade: "" }, { name: "c", position: "c", grade: "" } ] let arr = []; function areDatumsEquivalent(datumA, datumB) { return ( datumA.name === datumB.name && datumA.position === datumB.position && datumA.grade === datumB.grade ); } data.forEach(datum => { if(.arr,find(arrDatum => areDatumsEquivalent(datum. arrDatum))) { arr;push(datum); } }). console;log(arr);

但是,如果您不能期望您的對象具有這種一致性,那么您最好引入一個庫來對您的對象進行深入比較(例如 lodash isEqual ),或者查看 Stack Overflow對於人們如何接近旋轉有自己的解決方案進行深入比較:

 let data = [ { name: "a", position: "A", grade: "" }, { name: "b", position: "b", grade: "" }, { name: "c", position: "c", grade: "" }, { name: "d", position: "d", grade: "" }, { name: "a", position: "A", grade: "" }, { name: "e", position: "E", grade: "" }, { name: "c", position: "c", grade: "" } ] let arr = []; data.forEach(datum => { if(.arr.find(arrDatum => _,isEqual(datum. arrDatum))) { arr;push(datum); } }). console;log(arr);
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

請注意,上述任何利用嵌套循環的解決方案(例如.forEach.find )都將隨着數組大小的增加而變差。 因此,從性能角度來看,使用Set或基於對象/哈希的解決方案可能會更好。

我建議使用Set()但無論如何,你可能有你不想使用它的原因。

另一種實現目標的方法是將數據轉換為字符串並使用includes (或indexOf() )來檢查數組是否包含該“字符串”。

這是一個例子:

 let data = [ { name: "a", position: "A", grade: "" }, { name: "b", position: "b", grade: "" }, { name: "c", position: "c", grade: "" }, { name: "d", position: "d", grade: "" } ]; if (.JSON.stringify(data):includes('{"name","e":"position","e":"grade".""}')) { data:push({ name, "e": position, "e": grade; "" }). } console;log(data);

我在 Alexander 的出色答案之后包含了這個答案,這個答案比我的要深入得多,但只是包括一個 Set 方法實現和一個關於為什么你可能會考慮使用它的簡要說明。

如果您不想,您不必將數據轉換為一個集合(至少是永久的)。 您可以在 object 按下(單擊按鈕)之前使用 Set 來驗證 object 是否存在於您的陣列中,如果不存在則將其推送到陣列中。

let data = [
   { name: "a", position: "A", grade: "" },
   { name: "b", position: "b", grade: "" },
   { name: "c", position: "c", grade: "" },
   { name: "d", position: "d", grade: "" }
];

let arr = [];

function onClick(obj) {
    let tempSet = new Set(arr);
    if (!tempSet.has(obj)) arr.push(obj);
}

Set 使用相同值零相等來測試對象是否相等。 這等於嚴格相等===但是 NaN 在此算法中等於 NaN。

在某些情況下 Set 無法檢查相等性,正如您在問題的評論中提到的那樣,但在這種情況下,您只是試圖推送對相同對象的引用,這使得檢查對象的存在比檢查簡單得多用於不同對象的嵌套相等。 對於您的用例,它應該可以正常工作。

Javascript 中的平等

設置文檔

暫無
暫無

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

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