javascript ES6 - 从对象数组中删除重复项

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/53542882/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 10:14:19  来源:igfitidea点击:

ES6 - Removing duplicates from array of objects

javascriptdictionaryfilteruniquereduce

提问by Andy

Assuming an array of objects as follows:

假设一个对象数组如下:

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

A duplicate entry would be if label and color are the same. In this case Objects with id = 1 and id = 5 are duplicates.

如果标签和颜色相同,则会出现重复条目​​。在这种情况下,id = 1 和 id = 5 的对象是重复的。

How can I filter this array and remove duplicates?

如何过滤此数组并删除重复项?

I know solutions where you can filter against one key with something like:

我知道解决方案,您可以使用以下方法针对一个键进行过滤:

const unique = [... new Set(listOfTags.map(tag => tag.label)]

But what about multiple keys?

但是多个键呢?

As per request in comment, here the desired result:

根据评论中的要求,这里是所需的结果:

[
    {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},
]

回答by Nina Scholz

You could use a Setin a closure for filtering.

您可以Set在闭包中使用 a进行过滤。

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

回答by Evert

I would tackle this by putting this into temporary Map with a composite key based on the properties you're interested in. For example:

我会根据您感兴趣的属性将其放入带有复合键的临时 Map 中来解决这个问题。例如:

const foo = new Map();
for(const tag of listOfTags) {
  foo.set(tag.id + '-' tag.color, tag);
}

回答by charlietfl

One way is create an object (or Map) that uses a combination of the 2 values as keys and current object as value then get the values from that object

一种方法是创建一个对象(或 Map),它使用 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)

回答by COLBY BROOKS

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

回答by Ankit Arya

You can use reduce here to get filtered objects.

您可以在此处使用 reduce 来获取过滤的对象。

listOfTags.reduce((newListOfTags, current) => {
    if (!newListOfTags.some(x => x.label == current.label && x.color == current.color)) {
        newListOfTags.push(current);
    }
    return newListOfTags;
}, []);

回答by B12Toaster

Based on the assumption that values can be converted to strings, you can call

基于值可以转换为字符串的假设,您可以调用

distinct(listOfTags, ["label", "color"])

where distinctis:

在哪里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());
};

Sidenote: If you use distinct(listOfTags, ["label", "color"], false), it will return:

旁注:如果您使用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},
]