软科小院

javascript - 数组去重的问题

热度:19℃ 发布时间:2021-11-13 14:27:55

问题描述

假设现在有一个对象数组

arr=[ { id:1, content:’a’ },{ id:2, content:’b’ },{ id:2, content:’c’ },{ id:3, content:’d’ },{ id:3, content:’e’ },{ id:3, content:’f’ },{ id:3, content:’g’ },{ id:4, content:’h’ },]

我想去掉相同的id 然后保留各个id的最后一项

arr=[ { id:1, content:’a’ },{ id:2, content:’c’ },{ id:3, content:’g’ },{ id:4, content:’h’ },]

有什么好一点的方法嘛。。

问题解答

回答1:

按惯例,ES6 代码

const result = arr.reduce((r, t) => { // 在结果中查找 index, // 如果找到,更新该位置的对象引用 // 找到则加一个 var i = r.findIndex(m => m.id === t.id); if (i >= 0) { r[i] = t; } else { r.push(t); } return r;}, []);

这里有一个问题,findIndex 至少有两个浏览器不支持,所以,如果不支持的话,只好自己写一个

Array.prototype.findIndex = Array.prototype.findIndex || function(predicate) { for (let i = 0; i < this.length; i++) { if (predicate(this[i])) { return i; } } return -1;};

其它解法

经典解决,用 Map

因为 id 不是字符串,所以使用 ES6 的 Map 类。当数据量大的时候,使用查找表,比在列表中线性查找,效率会有显著的提升。

const result = arr .reduce((m, t) => { const { map, list } = m; var index = map.get(t.id); if (index >= 0) { list[index] = t; } else { map.set(t.id, list.length); list.push(t); } return m; }, { map: new Map(), list: [] }) .list;

其实也可以用对象来代替 map,至少在这个用例中不会有问题。因为没用 es6 特性,索性完全使用 es5 语法。代码结构和逻辑与上面那段一样

var result = arr .reduce(function(m, t) { var index = m.map[t.id]; if (index >= 0) { m.list[index] = t; } else { m.map[t.id] = m.list.length; m.list.push(t); } return m; }, { map: {}, list: [] }) .list;怪异解法,利用整数 id

因为是整数 id,所以可以直接按这个 id 放在数组中。如果遇到相同 id,直接就替换了。如果 id 不连续,最后需要把空元素过滤掉

var result = arr .reduce(function(r, t) { r[t.id] = t; return r; }, []) .filter(function(t) { return t; });

这种解法还有个问题,不能保持原数组的元素顺序。然后肯定会有人想到,用 Map 的那个解法也可以把代码精减成类似的代码,而不需要搞那么复杂,当然它也同样可能失去原有顺序

const map = arr .reduce((m, t) => { m.set(t.id, t); return m; }, new Map());const result = [...map.values()];

注:以上所有代码均实际运行通过,运行环境 Node v8.1.2

回答2:

var result = arr.filter(function(val, index) { /** * 使用arr.slice(index + 1)获取从当前索引下一个元素到数组最后一个元素组成的数组 * 使用findIndex在当前项的后面选项中查找是否有和当前项id值相同的选项 */ var index = arr.slice(index + 1).findIndex(function(item) { return item.id === val.id; }); // 如果为-1,则说明后面没有同名id了,所以这一项可以返回 return index === -1;});console.log(result);

使用箭头函数简化如下:

var result = arr.filter((val, index) => arr.slice(index + 1).findIndex(item => item.id === val.id) === -1);console.log(result);回答3:

这里面已经有很多答案了,不过没有提到Array的内置函数reduceRight,实际上题主的需求,要求保留相同id的最后一位,用reduceRight实现起来很方便。

arr.reduceRight((r,v)=>{ if(!r[0].has(v.id)) r[0].add(v.id) && r[1].unshift(v) return r},[new Set,[]])[1]

reduceRight从你原数组尾部开始循环的,我这里的初始值是个数组,r[0]用来存放id的Set,r[1]存放结果数组,如果Set里没有id,那么就添加这个id到Set,并且把这一项放在结果数组的头部。

最终很容易的实现了题主的需求,而且顺序也能保证。

回答4:

function uniq(arr) { var idArr = [],arr2 = [] for (var i = 0, len = arr.length; i < len; i++) { if (arr[i].id in idArr) { arr2.pop() arr2.push(arr[i]) } else { idArr.push(arr[i].id) arr2.push(arr[i]) } } return arr2}

亲测有效

回答5:

arr = [ { id: 1, content: ’a’ }, { id: 2, content: ’b’ }, { id: 2, content: ’c’ }, { id: 3, content: ’d’ }, { id: 3, content: ’e’ }, { id: 3, content: ’f’ }, { id: 3, content: ’g’ }, { id: 4, content: ’h’ } ] tmp = []for(k in arr){tmp[arr[k][’id’]] = arr[k][’content’]}arr = []for(k in tmp){arr.push({’id’:+k, ’content’:tmp[k]})}console.log(arr)[ { id: 1, content: ’a’ }, { id: 2, content: ’c’ }, { id: 3, content: ’g’ }, { id: 4, content: ’h’ } ]回答6:

let newArr = [],

result = [], status = false, lastResult = []for (let i = arr.length - 1; i >= 0; i--) { newArr.push(arr[i])}for (let i = 0, len = newArr.length; i < len; i++) { if (result.length == 0) { result.push(newArr[0]) } for (let j = 0; j < result.length; j++) { if (newArr[i].id == result[j].id) { console.log(newArr[i]) status = true } } if (!status) { result.push(newArr[i]) } status = false}for (let i = result.length - 1; i >= 0; i--) { lastResult.push(result[i])}console.log(lastResult) //为去掉相同的id 然后保留各个id的最后一项回答7:

var arr = [ ... ]; // 这个为给定的数组var obj = {}; // 定义一个对象存储arr.forEach(function(v) { obj[v.id] = v; // 不管如何,直接将数组赋值给obj中下标为v.id的项,这样对应的v.id的值到最后必然是同ID最后一项});// 下面考虑兼容性给出新语法和常规语法// 新语法,Object.values部分浏览器版本不支持var result = Object.values(obj);// 常规语法,用Array.map实现Object.values的效果var result = Object.keys(obj).map(function(id) { return obj[id];});回答8:

参考一下

Array.from(arr.reduce((map, el) => map.set(el.id, el), new Map()).values())回答9:

你可以参考我博客写的,我博客上写了8中方法。http://alfierichou.top/2017/0...

网友评论
评论
发 布

更多常见问答
  • 常见问答推荐
更多+
最新软件下载