如何从具有唯一标识符的 JavaScript 数组中删除重复项

huangapple go评论130阅读模式
英文:

How to Remove duplicates from javascript array having one unique identifier

问题

我有一个数组如下:
```lang-js
let arr =
  [ { id: 1, name: ''a'', age: 10 }
  , { id: 2, name: ''a'', age: 10 }
  , { id: 3, name: ''b'', age: 11 }
  ]

我想要移除重复的对象,我在寻找一个优化的解决方案。
解决方案应该是通用的,不应该绑定在对象属性名称上,除了 "id" 属性。
我的意思是它应该也适用于下面的数组...

    [
     {id:1, emp_name:''x'', sal:33},
     {id:2, emp_name:''x'', sal:33},
     {id:3, emp_name:''z'', sal:35}
    ]

我期望的结果是

  [ { id: 1, name: ''a'', age: 10 }
  , { id: 3, name: ''b'', age: 11 }
  ]

或者

    [
     {id:1, emp_name:''x'', sal:33},
     {id:3, emp_name:''z'', sal:35}
    ]
英文:

I have an array like

let arr = 
  [ { id: 1, name: 'a', age: 10 } 
  , { id: 2, name: 'a', age: 10 } 
  , { id: 3, name: 'b', age: 11 } 
  ] 

I want to remove duplicate objects I am looking for an optimize solution.
solution should be generic and should not be bound with object properties name except "id" property.
I mean it should work for below array also ..

    [
     {id:1, emp_name:'x', sal:33},
     {id:2, emp_name:'x', sal:33},
     {id:3, emp_name:'z', sal:35}
    ] 

I am expecting

  [ { id: 1, name: 'a', age: 10 } 
  , { id: 3, name: 'b', age: 11 } 
  ] 

or

    [
     {id:1, emp_name:'x', sal:33},
     {id:3, emp_name:'z', sal:35}
    ] 

答案1

得分: 1

使用`Array.splice()`方法来删除数组元素

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

    let arr = 
      [ { id: 1, name: 'a', age: 10 } 
      , { id: 2, name: 'a', age: 10 } 
      , { id: 3, name: 'b', age: 11 } 
      ];

    for(let i=arr.length;--i>0;) // 需要从后往前处理
      {
      if (i > arr.findIndex(e=>e.name===arr[i].name && e.age===arr[i].age))
        arr.splice(i,1);
      }

    console.log(arr)

<!-- language: lang-css -->

    .as-console-wrapper {max-height: 100% !important;top: 0;}
    .as-console-row::after {display: none !important;}

<!-- end snippet -->


**通用解决方案**

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

    const
      arr1 = 
        [ { id: 1, name: 'a', age: 10 } 
        , { id: 2, name: 'a', age: 10 } 
        , { id: 3, name: 'b', age: 11 } 
        ]
    , arr2 = 
        [ { id:1, emp_name:'x', sal:33 }
        , { id:2, emp_name:'x', sal:33 }
        , { id:3, emp_name:'z', sal:35 }
        ];

    removeDuplicates(arr1);
    console.log('arr1-->', arr1);
     
    removeDuplicates(arr2);
    console.log('arr2-->', arr2);
     
    
    function removeDuplicates(arr)
      {
      let keys = Object.keys(arr[0]).reduce((kn,k)=>((k==='id')?null:kn.push(k),kn),[]);
          // 获取键名(除'id'外的)
     
      for(let i=arr.length;--i>0;) // 需要从后往前处理
        {
        if (i >  arr.findIndex(e=>keys.reduce((b,k)=> b && e[k]===arr[i][k] ,true))) 
          arr.splice(i,1);
        }
      }

<!-- language: lang-css -->

    .as-console-wrapper {max-height: 100% !important;top: 0;}
    .as-console-row::after {display: none !important;}

<!-- end snippet -->
英文:

to REMOVE an array element use Array.splice() method

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let arr = 
  [ { id: 1, name: &#39;a&#39;, age: 10 } 
  , { id: 2, name: &#39;a&#39;, age: 10 } 
  , { id: 3, name: &#39;b&#39;, age: 11 } 
  ];

for(let i=arr.length;--i&gt;0;) // need to progress backward
  {
  if (i &gt; arr.findIndex(e=&gt;e.name===arr[i].name &amp;&amp; e.age===arr[i].age))
    arr.splice(i,1);
  }

console.log(arr)

<!-- language: lang-css -->

.as-console-wrapper {max-height: 100% !important;top: 0;}
.as-console-row::after {display: none !important;}

<!-- end snippet -->

Generic solution

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const
  arr1 = 
    [ { id: 1, name: &#39;a&#39;, age: 10 } 
    , { id: 2, name: &#39;a&#39;, age: 10 } 
    , { id: 3, name: &#39;b&#39;, age: 11 } 
    ]
, arr2 = 
    [ { id:1, emp_name:&#39;x&#39;, sal:33 }
    , { id:2, emp_name:&#39;x&#39;, sal:33 }
    , { id:3, emp_name:&#39;z&#39;, sal:35 }
    ];

removeDuplicates(arr1);
console.log(&#39;arr1--&gt;&#39;, arr1);
 
removeDuplicates(arr2);
console.log(&#39;arr2--&gt;&#39;, arr2);
 

function removeDuplicates(arr)
  {
  let keys = Object.keys(arr[0]).reduce((kn,k)=&gt;((k===&#39;id&#39;)?null:kn.push(k),kn),[]);
      // get key names (except &#39;id&#39;)
 
  for(let i=arr.length;--i&gt;0;) // need to progress backward
    {
    if (i &gt;  arr.findIndex(e=&gt;keys.reduce((b,k)=&gt; b &amp;&amp; e[k]===arr[i][k] ,true))) 
      arr.splice(i,1);
    }
  }

<!-- language: lang-css -->

.as-console-wrapper {max-height: 100% !important;top: 0;}
.as-console-row::after {display: none !important;}

<!-- end snippet -->

答案2

得分: 0

我会做这样的事情
```javascript
或者如果你不想创建新的数组、映射等等:
```javascript
你也可以反向循环数组这样就不需要修复索引递增或循环的长度
```javascript
此外,如果你的id属性可能不是第一个键:
```javascript
英文:

I would do something like this

const res = arr.reduce(
	(acc, x) =&gt;
		!acc.has(Object.values(x).slice(1).join(&#39;&#39;))
			? acc.set(Object.values(x).slice(1).join(&#39;&#39;), x)
			: acc,
	new Map()
)
console.log(Array.from(res.values()))

Or if you don't want to make new arrays, maps and so on:

for (let i = 0, remove = false; i &lt; arr.length; !remove &amp;&amp; i++) {
	remove =
		arr.findIndex(
			(t, ti) =&gt;
				ti &lt; i &amp;&amp;
				Object.values(arr[i]).every(
					(x, j) =&gt; j === 0 || x === Object.values(t)[j]
				)
		) + 1
	if (remove) arr.splice(i, 1)
}

You can loop through array backwards as well so you don't need to fix the index increment or the length of loop.

for (let i = arr.length - 1; i &gt;= 0; i--) {
	let duplicateIdx = arr.findIndex(t =&gt;
		Object.values(arr[i]).every((x, j) =&gt; j === 0 || x === Object.values(t)[j])
	)
	if (duplicateIdx !== -1 &amp;&amp; duplicateIdx &lt; i) arr.splice(i, 1)
}

Also if your id property may not be the 1st key:

for (let i = arr.length - 1; i &gt;= 0; i--) {
	let duplicateIdx = arr.findIndex(t =&gt;
		Object.keys(arr[i]).every(key =&gt; key === &#39;id&#39; || arr[i][key] === t[key])
	)
	if (duplicateIdx !== -1 &amp;&amp; duplicateIdx &lt; i) arr.splice(i, 1)
}

答案3

得分: 0

我已经创建了下面的代码,但我正在寻找一个更优化的版本。。

英文:

I have created below but I am looking for more optimized one ..

for(let i=0;i&lt;arr.length;i++)
  {
    for(let j=i+1;j&lt;arr.length;j++)
      { 
        let o1 =  {...arr[i]};
        let o2 =  {...arr[j]};       
		delete o1.id ;delete o2.id ;                
        if(JSON.stringify(o1) === JSON.stringify(o2))
        {          
          arr.splice(i,1);          
        }
      }
  }

console.log(JSON.stringify(arr));

huangapple
  • 本文由 发表于 2023年3月10日 01:13:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/75687909.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定