Heim > Fragen und Antworten > Hauptteil
Angenommen, es gibt jetzt eine Reihe von Objekten
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'
},
]
Ich möchte dieselbe ID entfernen und das letzte Element jeder ID behalten
arr=[
{
id:1,
content:'a'
},{
id:2,
content:'c'
},{
id:3,
content:'g'
},{
id:4,
content:'h'
},
]
Gibt es einen besseren Weg? .
漂亮男人2017-06-28 09:26:12
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;
};
因为 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 不连续,最后需要把空元素过滤掉
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
某草草2017-06-28 09:26:12
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);
仅有的幸福2017-06-28 09:26:12
这里面已经有很多答案了,不过没有提到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,并且把这一项放在结果数组的头部。
最终很容易的实现了题主的需求,而且顺序也能保证。
曾经蜡笔没有小新2017-06-28 09:26:12
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
}
亲测有效
伊谢尔伦2017-06-28 09:26:12
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' } ]
滿天的星座2017-06-28 09:26:12
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的最后一项
学习ing2017-06-28 09:26:12
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];
});
天蓬老师2017-06-28 09:26:12
参考一下
Array.from(arr.reduce((map, el) => map.set(el.id, el), new Map()).values())