次のようにオブジェクトの配列を想定します。
const listOfTags = [
{id: 1, label: "Hello", color: "red", sorting: 0},
{id: 2, label: "World", color: "green", sorting: 1},
{id: 3, label: "Hello", color: "blue", sorting: 4},
{id: 4, label: "Sunshine", color: "yellow", sorting: 5},
{id: 5, label: "Hello", color: "red", sorting: 6},
]
ラベルと色が同じ場合、エントリが重複します。この場合、id = 1およびid = 5のオブジェクトは重複しています。
この配列をフィルタリングして重複を削除するにはどうすればよいですか?
私はあなたが1つのキーに対して次のようなものでフィルタリングできるソリューションを知っています:
const unique = [... new Set(listOfTags.map(tag => tag.label)]
しかし、複数のキーはどうですか?
コメントのリクエストに従って、ここで望ましい結果:
[
{id: 1, label: "Hello", color: "red", sorting: 0},
{id: 2, label: "World", color: "green", sorting: 1},
{id: 3, label: "Hello", color: "blue", sorting: 4},
{id: 4, label: "Sunshine", color: "yellow", sorting: 5},
]
Set
をフィルターのクロージャーで使用できます。
const
listOfTags = [{ id: 1, label: "Hello", color: "red", sorting: 0 }, { id: 2, label: "World", color: "green", sorting: 1 }, { id: 3, label: "Hello", color: "blue", sorting: 4 }, { id: 4, label: "Sunshine", color: "yellow", sorting: 5 }, { id: 5, label: "Hello", color: "red", sorting: 6 }],
keys = ['label', 'color'],
filtered = listOfTags.filter(
(s => o =>
(k => !s.has(k) && s.add(k))
(keys.map(k => o[k]).join('|'))
)
(new Set)
);
console.log(filtered);
.as-console-wrapper { max-height: 100% !important; top: 0; }
これに取り組むには、興味のあるプロパティに基づいた複合キーを使用して、これを一時的なマップに入れます。次に例を示します。
const foo = new Map();
for(const tag of listOfTags) {
foo.set(tag.id + '-' tag.color, tag);
}
値を文字列に変換できるという仮定に基づいて、次を呼び出すことができます
_distinct(listOfTags, ["label", "color"])
_
ここで、distinct
は次のとおりです。
_/**
* @param {array} arr The array you want to filter for dublicates
* @param {array<string>} indexedKeys The keys that form the compound key
* which is used to filter dublicates
* @param {boolean} isPrioritizeFormer Set this to true, if you want to remove
* dublicates that occur later, false, if you want those to be removed
* that occur later.
*/
const distinct = (arr, indexedKeys, isPrioritizeFormer = true) => {
const lookup = new Map();
const makeIndex = el => indexedKeys.reduce(
(index, key) => `${index};;${el[key]}`, ''
);
arr.forEach(el => {
const index = makeIndex(el);
if (lookup.has(index) && isPrioritizeFormer) {
return;
}
lookup.set(index, el);
});
return Array.from(lookup.values());
};
_
傍注:distinct(listOfTags, ["label", "color"], false)
を使用すると、次が返されます:
_[
{id: 1, label: "Hello", color: "red", sorting: 6},
{id: 2, label: "World", color: "green", sorting: 1},
{id: 3, label: "Hello", color: "blue", sorting: 4},
{id: 4, label: "Sunshine", color: "yellow", sorting: 5},
]
_
1つの方法は、2つの値の組み合わせをキーとして使用し、現在のオブジェクトを値として使用するオブジェクト(またはマップ)を作成し、そのオブジェクトから値を取得することです
const listOfTags = [
{id: 1, label: "Hello", color: "red", sorting: 0},
{id: 2, label: "World", color: "green", sorting: 1},
{id: 3, label: "Hello", color: "blue", sorting: 4},
{id: 4, label: "Sunshine", color: "yellow", sorting: 5},
{id: 5, label: "Hello", color: "red", sorting: 6},
]
const uniques = Object.values(
listOfTags.reduce((a, c) => {
a[c.label + '|' + c.color] = c;
return a
}, {}))
console.log(uniques)
const listOfTags = [
{id: 1, label: "Hello", color: "red", sorting: 0},
{id: 2, label: "World", color: "green", sorting: 1},
{id: 3, label: "Hello", color: "blue", sorting: 4},
{id: 4, label: "Sunshine", color: "yellow", sorting: 5},
{id: 5, label: "Hello", color: "red", sorting: 6},
]
const unique = [];
listOfTags.map(x => unique.filter(a => a.label == x.label && a.color == x.color).length > 0 ? null : unique.Push(x));
console.log(unique);
ここでreduceを使用して、フィルターされたオブジェクトを取得できます。
listOfTags.reduce((newListOfTags, current) => {
if (!newListOfTags.some(x => x.label == current.label && x.color == current.color)) {
newListOfTags.Push(current);
}
return newListOfTags;
}, []);