简体   繁体   English

有条件地从对象数组中删除重复项

[英]Remove duplicates from array of objects conditionally

I've got an array of objects which have a property in common 'label'.我有一组对象,它们具有共同的“标签”属性。 But some of them have properties that others don't :但其中一些具有其他人没有的特性:

const array = [
    {
        label: 'thing',
        type: 'reg',
    },
    {
        label: 'thing',
        type: 'ville',
        id: 1,
    },
    {
        label: 'another_thing',
        type: 'ville',
        id: 2,
    },
    {
        label: 'something',
        type: 'dpt',
    }
];

And I want duplicates (those objects with the same 'label' value) in this array to be removed and to keep only those which have the 'id' property.我希望删除此数组中的重复项(具有相同“标签”值的对象)并仅保留那些具有“id”属性的对象。 I tried to do it with _.uniqBy but it takes the first occurrence of the duplicated object and doesn't take the id property in consideration.我试图用 _.uniqBy 来做,但它需要重复对象的第一次出现并且不考虑 id 属性。

So my final array should look like because the duplicate with the same 'label' value but which has no id property has been removed :所以我的最终数组应该看起来像,因为具有相同“标签”值但没有 id 属性的重复项已被删除:

const array = [
    {
        label: 'thing',
        type: 'ville',
        id: 1,
    },
    {
        label: 'another_thing',
        type: 'ville',
        id: 2,
    },
    {
        label: 'something',
        type: 'dpt',
    }
];

Reduce the array to a Map .将数组缩减为Map If the item has an id or the label doesn't exist in the Map, add it to the Map.如果项目有idlabel在 Map 中不存在,则将其添加到 Map。 Convert the Map's .values() iterator to an array using Array.from() :使用Array.from()将 Map 的.values()迭代器转换为数组:

 const array = [{"label":"thing","type":"reg"},{"label":"thing","type":"ville","id":1},{"label":"something","type":"dpt"}]; const result = Array.from( // convert the Map's iterator to an array array.reduce((r, o) => 'id' in o || !r.has(o.label) ? // if the item has an id or it doesn't exist in the Map r.set(o.label, o) // add it to the Map and return the Map : r // just return the Map , new Map() ).values()); // convert to an iterator console.log(result);

You can use a map to store items by their key and use a filter function to determine if an item is eligible to be overwritten.您可以使用映射按键存储项目,并使用过滤器功能确定项目是否有资格被覆盖。

 const array = [ { label: 'thing', type: 'reg' }, { label: 'thing', type: 'ville', id: 1 }, { label: 'something', type: 'dpt' } ]; const filterUnique = (list, key, filterFn) => [ ...list.reduce((result, item) => { if (!result.has(item[key]) || filterFn(item)) { result.set(item[key], item); } return result; }, new Map()).values() ]; console.log(filterUnique(array, 'label', item => item.id));
 .as-console-wrapper { top: 0; max-height: 100% !important; }

We can achieve this using Array.reduce and Object.values我们可以使用Array.reduceObject.values Array.reduce实现

 const array = [{label:'thing',type:'reg'},{label:'thing',type:'ville',id:1},{label:'another_thing',type:'ville',id:2},{label:'something',type:'dpt'}]; const filterData = (data) => { const finalResult = data.reduce((res, obj) => { //Check if the object is already present in the `res` object with key as `obj.label` //If not found, add the obj to result if(!res[obj.label]) { res[obj.label] = obj; } else if(obj.hasOwnProperty("id")) { //If found, check the new obj has property `id`, if available then override //result object with key as `obj.label` with new object res[obj.label] = obj } return res; }, {}) //Return the values of the finalResult object return Object.values(finalResult); } console.log(filterData(array))
 .as-console-wrapper { max-height: 100% !important; }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM