web-dev-qa-db-de.com

ES6 - Duplikate aus einem Array von Objekten entfernen

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},
]
5
Andy

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; }

3
Nina Scholz

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);
}
2
Evert

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},
]
1
B12Toaster

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)

1
charlietfl

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

1
COLBY BROOKS

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;
}, []);
0
Ankit Arya