Nehmen Sie ein Array von Objekten wie folgt an:
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},
]
Ein doppelter Eintrag wäre, wenn Beschriftung und Farbe gleich sind. In diesem Fall sind Objekte mit id = 1 und id = 5 Duplikate.
Wie kann ich dieses Array filtern und Duplikate entfernen?
Ich kenne Lösungen, bei denen Sie anhand eines Schlüssels nach etwas filtern können:
const unique = [... new Set(listOfTags.map(tag => tag.label)]
Aber was ist mit mehreren Schlüsseln?
Wie auf Anfrage im Kommentar, hier das gewünschte Ergebnis:
[
{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},
]
Sie können eine Set
in einer Schließung zum Filtern verwenden.
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; }
Ich würde dieses Problem angehen, indem Sie dies in eine temporäre Map mit einem zusammengesetzten Schlüssel aufnehmen, der auf den gewünschten Eigenschaften basiert. Zum Beispiel:
const foo = new Map();
for(const tag of listOfTags) {
foo.set(tag.id + '-' tag.color, tag);
}
Ausgehend von der Annahme, dass Werte in Strings konvertiert werden können, können Sie sie aufrufen
distinct(listOfTags, ["label", "color"])
wo distinct
ist:
/**
* @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());
};
Randbemerkung: Wenn Sie distinct(listOfTags, ["label", "color"], false)
verwenden, wird Folgendes zurückgegeben:
[
{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},
]
Eine Möglichkeit besteht darin, ein Objekt (oder eine Karte) zu erstellen, das eine Kombination der beiden Werte als Schlüssel und das aktuelle Objekt als Wert verwendet und dann die Werte von diesem Objekt abruft
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);
Sie können hier verkleinern verwenden, um gefilterte Objekte zu erhalten.
listOfTags.reduce((newListOfTags, current) => {
if (!newListOfTags.some(x => x.label == current.label && x.color == current.color)) {
newListOfTags.Push(current);
}
return newListOfTags;
}, []);