假設現在有一個物件數組
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'
},
]
有什麼好一點的方法嘛。 。
漂亮男人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
參考一下
Array.from(arr.reduce((map, el) => map.set(el.id, el), new Map()).values())