2017-05-01 14 views
1

私は配列にアイテムを追加する方法をいくつか書いていました。その方法では、配列に既に入っていれば無視されます。データ構造についていくつかの研究をした後、重複を取り除くことができることがわかりました(特にオブジェクトの順序は気にしません)。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); 

が出力:しかし、JavaScriptでプレーした後、私は同じオブジェクトが集合、例に追加されていることに気づいた。この例では

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

、私はキー - > Aと値を持つオブジェクトを追加します - > 23、次に全く異なるキーと値のセットを持つ別のもの、そして元のものを再度設定します。私は自分のセットにa-> 23とb-> 14しか持たないと思います。

リストに重複を取り除く最良の方法は何ですか?

+2

簡単な例を、コンソールのタイプ '{23} == {23}' 。 –

+0

「連想配列」のキーとして 'JSON.stringify()'を利用するのが好きですが、それが「最良の」方法であるかどうかは分かりません –

+1

あなたの問題は、それらが "同一のオブジェクト"実際、それらは異なるオブジェクトを指し示す異なる参照である。重複を削除する方法に関する質問に答える前に、まず「重複」が何を意味するのかを定義する必要があります。プロパティの同じセットを持つオブジェクト?プロパティのセットは同じですが、プロトタイプが異なるオブジェクトはどうですか?彼らは "重複"ですか? –

答えて

3

誰もが言ったように、オブジェクトは等しくないので、重複しているように見えます。私が推測しているキーをa、b、cなどと指定することができれば、マップを使うことができます。 iterableもあります。

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

console.log(myMap) 

地図{ "" => 33、 "B" => 123}(2)

+2

keyが文字列の場合、実際には 'Map'は必要ありません。代わりに標準オブジェクトを使うことができます。 –

+0

ええ、マップはiterableでOPが配列を表しているので、少し面白くて便利ですが、どちらも私にとってはうまくいきます。 – dashton

4

これらのオブジェクトは、同じ構造を持ちますが、区別されます。それぞれはメモリ内の別々の空間を表し、そのメモリへの一意の参照です。

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

あなたは、彼らが代わりに参照の等価の含まれたデータに基づいてオブジェクトを比較するのユースケースをサポートしたい場合は、あなたがに見たいと思うかもしれませんこと01​​です。

例えば、ここでオブジェクトは、それを追加する前に、アレイ内に存在するかどうかをチェックするためにdeep-equalライブラリを利用する一つの方法です:

!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)である。ディープオブジェクト比較メソッドのほとんどのバージョンは再帰的な方法で記述されているため、現代の環境でテール再帰関数ではないと仮定すると、空間の複雑さが定数から線形に増加します。

+2

私は本当になぜこの正解が2度下降されたのだろうと思っています。 – Bergi

+2

@Bergiはわかりません。彼らは少なくとも彼らが間違っていると思っているものにフィードバックを与えていれば役に立ちました。 – nem035

+1

ありがとうございます@ nem035、誰かがセットを使用しなければならなかった場合、あなたの答えは完璧だったでしょうが、簡単にするために私のマップは私のアプリケーションにとってより意味をなさないと思います。なぜ誰もあなたの答えに投票しない理由を確かめないでください。 –

関連する問題