重複したオブジェクトの配列があり、一意のリストを取得しようとしています。一意性はオブジェクトのプロパティのサブセットによって定義されます。例えば、
{a:"1",b:"1",c:"2"}
そして、一意性の比較でc
を無視したいと思います。
私は次のようなことができます
_.uniq(myArray,function(element) { return element.a + "_" + element+b});
私はできることを望んでいた
_.uniq(myArray,function(element) { return {a:element.a, b:element.b} });
しかし、それは機能しません。私ができるようなことはありますか、または複数のプロパティを比較している場合、オブジェクトの同等の表現を作成する必要がありますか?
残念ながら、これを行う簡単な方法はないようです。このために独自の関数を書くのではなく、(最初の例のように)等価性を直接比較できるものを返す必要があります。
1つの方法は、必要なプロパティを.join()
するだけです:
__.uniqBy(myArray, function(elem) { return [elem.a, elem.b].join(); });
_
あるいは、 __.pick
_ または __.omit
_ を使用して、不要なものをすべて削除できます。そこから、.join()
とともに__.values
_を使用することも、単に_JSON.stringify
_を使用することもできます。
__.uniqBy(myArray, function(elem) {
return JSON.stringify(_.pick(elem, ['a', 'b']));
});
_
プロパティの順序に関する限り、オブジェクトは決定論的ではないことに注意してください。したがって、明示的な配列アプローチに固執することをお勧めします。
追伸Lodash <4のuniqBy
をuniq
に置き換えます
Join()アプローチは今でも最も簡単だと思います。以前のソリューションで懸念が生じたにもかかわらず、正しいセパレーターを選択することは、特定の落とし穴(異なる値セットで同じ結合値を返す)を回避するための鍵だと思います。セパレータは単一の文字である必要はなく、データ自体には自然に発生しないと確信できる任意の文字列を使用できます。私は常にこれを行い、セパレータとして「〜!$〜」を使用するのが好きです。\t\r\nなどの特殊文字を含めることもできます。
含まれているデータが本当に予測不可能な場合、おそらく最大長がわかっているので、結合する前に各要素をその最大長まで単純に埋めることができます。
Lodashの uniqWith
メソッドを使用します。
_.uniqWith(array, [comparator])
このメソッドは
_.uniq
は、comparator
の要素を比較するために呼び出されるarray
を受け入れることを除きます。結果値の順序は、配列内で発生する順序によって決まります。コンパレータは、2つの引数で呼び出されます:(arrVal、othVal)。
comparator
がtrue
を返す場合、アイテムは重複していると見なされ、最初の出現のみが新しい配列に含まれます。
例:
私はlatitude
とlongitude
を持つ場所のリストを持っています-そのうちのいくつかは同一です-そして、私はユニークな場所のリストを見たいです
const locations = [
{
name: "Office 1",
latitude: -30,
longitude: -30
},
{
name: "Office 2",
latitude: -30,
longitude: 10
},
{
name: "Office 3",
latitude: -30,
longitude: 10
}
];
const uniqueLocations = _.uniqWith(
locations,
(locationA, locationB) =>
locationA.latitude === locationB.latitude &&
locationA.longitude === locationB.longitude
);
// Result has Office 1 and Office 2
@voithosと@Danailを組み合わせた回答にはヒントがあります。これを解決する方法は、配列内のオブジェクトに一意のキーを追加することでした。
サンプルデータの開始
const animalArray = [
{ a: 4, b: 'cat', d: 'generic' },
{ a: 5, b: 'cat', d: 'generic' },
{ a: 4, b: 'dog', d: 'generic' },
{ a: 4, b: 'cat', d: 'generic' },
];
上記の例では、配列をa
とb
で一意にする必要がありますが、現在はa: 4
とb: 'cat'
を持つ2つのオブジェクトがあります。 a + bを文字列に結合することにより、確認する一意のキーを取得できます。
{ a: 4, b: 'cat', d: 'generic', id: `${a}-${b}` }. // id is now '4-cat'
注:同じオブジェクト内のオブジェクトのプロパティを参照できないため、オブジェクトの作成中にデータをマップするか、これを行う必要があることは明らかです。
今、比較は簡単です...
_.uniqBy(animalArray, 'id');
結果の配列の長さは3になり、最後の重複が削除されます。