[英]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 形狀,您可以為此編寫自己的檢查。 例如,在您的情況下,如果您可以預期您只會比較具有name
、 position
和grade
屬性的對象,您可以很容易地編寫一個自定義比較來處理這個問題:
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 無法檢查相等性,正如您在問題的評論中提到的那樣,但在這種情況下,您只是試圖推送對相同對象的引用,這使得檢查對象的存在比檢查簡單得多用於不同對象的嵌套相等。 對於您的用例,它應該可以正常工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.