簡體   English   中英

消除JavaScript列表中重復項的最佳方法是什么?

[英]What's the best way to get rid of duplicates in a JavaScript list?

我編寫了幾種方法,可以將項目添加到數組中,如果它們已經在數組中,則將被忽略。 在對數據結構進行了一些研究之后,我意識到只需將它們放在一個集合中就可以消除重復項(特別是因為我不在乎對象的順序)。 但是,在使用JavaScript之后,我注意到將相同的對象添加到集合中,例如:

var mySet = new Set();
mySet.add({a:23})
console.log(mySet);
mySet.add({b:14})
console.log(mySet);
mySet.add({a:23})
console.log(mySet);

輸出:

Set {Object {a: 23}}
Set {Object {a: 23}, Object {b: 14}}
Set {Object {a: 23}, Object {b: 14}, Object {a: 23}}

在此示例中,我添加了一個對象,該對象具有key-> a和value-> 23,然后添加另一個具有完全不同的key,value的對象,然后再添加原始對象。 我希望我的集合中只有a-> 23和b-> 14。

消除列表中重復項的最佳方法是什么?

這些對象盡管具有相同的結構,但卻是不同的。 每個代表內存中的單獨空間,並且是對該內存的唯一引用。

 console.log( { a: 23 } === { a: 23 } // false ); 

這樣可以將同一對象兩次添加到集合中,而第二次添加將被忽略。

 var obj = { a: 23 }; var s = new Set(); // first addition s.add(obj); console.log( ...s.values() ); // second addition of the same object is ignored s.add(obj); console.log( ...s.values() ); 

如果要支持根據對象包含的數據而不是引用相等來比較對象的用例,則可能要研究的是深度對象比較

例如,這是一種利用深度相等庫在添加對象之前檢查對象是否存在於數組中的方法:

 !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.deepEqual=e()}}(function(){return function e(t,r,n){function o(u,i){if(!r[u]){if(!t[u]){var c="function"==typeof require&&require;if(!i&&c)return c(u,!0);if(f)return f(u,!0);var p=new Error("Cannot find module '"+u+"'");throw p.code="MODULE_NOT_FOUND",p}var l=r[u]={exports:{}};t[u][0].call(l.exports,function(e){var r=t[u][1][e];return o(r?r:e)},l,l.exports,e,t,r,n)}return r[u].exports}for(var f="function"==typeof require&&require,u=0;u<n.length;u++)o(n[u]);return o}({1:[function(e,t,r){function n(e){return null===e||void 0===e}function o(e){return!(!e||"object"!=typeof e||"number"!=typeof e.length)&&("function"==typeof e.copy&&"function"==typeof e.slice&&!(e.length>0&&"number"!=typeof e[0]))}function f(e,t,r){var f,l;if(n(e)||n(t))return!1;if(e.prototype!==t.prototype)return!1;if(c(e))return!!c(t)&&(e=u.call(e),t=u.call(t),p(e,t,r));if(o(e)){if(!o(t))return!1;if(e.length!==t.length)return!1;for(f=0;f<e.length;f++)if(e[f]!==t[f])return!1;return!0}try{var s=i(e),a=i(t)}catch(e){return!1}if(s.length!=a.length)return!1;for(s.sort(),a.sort(),f=s.length-1;f>=0;f--)if(s[f]!=a[f])return!1;for(f=s.length-1;f>=0;f--)if(l=s[f],!p(e[l],t[l],r))return!1;return typeof e==typeof t}var u=Array.prototype.slice,i=e("./lib/keys.js"),c=e("./lib/is_arguments.js"),p=t.exports=function(e,t,r){return r||(r={}),e===t||(e instanceof Date&&t instanceof Date?e.getTime()===t.getTime():!e||!t||"object"!=typeof e&&"object"!=typeof t?r.strict?e===t:e==t:f(e,t,r))}},{"./lib/is_arguments.js":2,"./lib/keys.js":3}],2:[function(e,t,r){function n(e){return"[object Arguments]"==Object.prototype.toString.call(e)}function o(e){return e&&"object"==typeof e&&"number"==typeof e.length&&Object.prototype.hasOwnProperty.call(e,"callee")&&!Object.prototype.propertyIsEnumerable.call(e,"callee")||!1}var f="[object Arguments]"==function(){return Object.prototype.toString.call(arguments)}();r=t.exports=f?n:o,r.supported=n,r.unsupported=o},{}],3:[function(e,t,r){function n(e){var t=[];for(var r in e)t.push(r);return t}r=t.exports="function"==typeof Object.keys?Object.keys:n,r.shim=n},{}]},{},[1])(1)}); function addToSet(s, value) { for (const curr of s.values()) { if (deepEqual(curr, value)) { return; } } s.add(value); } var mySet = new Set(); // first addition works addToSet(mySet, {a:23}); console.log(...mySet.values()); // second addition works addToSet(mySet, {b:14}); console.log(...mySet.values()); // addition of an object of the same structure is ignored addToSet(mySet, {a:23}); console.log(...mySet.values()); 

在這種情況下,重要的考慮因素是deepEqual函數的時間/空間復雜度。 使用這種方法,將元素添加到集合中的時間復雜度從線性增加到至少二次,即O(setSize * numberOfPropsInLargestObject) 由於大多數版本的深度對象比較方法都是以遞歸方式編寫的,因此假設它不是現代環境中的尾部遞歸函數,這也會使空間復雜度從常量變為線性。

正如其他所有人所說,對象並不相等,因此它們似乎是重復的。 如果您可以指定一個鍵(假設它是a,b,c等),則可以使用地圖。 它也是可迭代的。

var myMap = new Map();
myMap.set('a',23);
myMap.set('b',123);
myMap.set('a',33);

console.log(myMap)

映射{“ a” => 33,“ b” => 123}(2)

暫無
暫無

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

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