說到交併集避免不了判斷類型是否相同,可能很多人都會想到ES6的Set
類型,理所當然的認爲可以用Set
類型來達到取唯一。但其實沒那麼簡單。
下面參考網上的一些代碼
let a = new Set([1, 2, 3]);
let b = new Set([3, 5, 2]);
// 並集
let unionSet = new Set([...a, ...b]);
//[1,2,3,5]
// 交集
let intersectionSet = new Set([...a].filter(x => b.has(x)));
// [2,3]
// ab差集
let differenceABSet = new Set([...a].filter(x => !b.has(x)));
// [1]
再把Set轉換爲數組即可.
let arr = Array.from(set);
// 或 let arr = [...set];
看起來沒有什麼問題,但是沒有考慮到數組的值類型爲Object
時,Set
的has()
方法是無法判斷的,會永遠返回false
。
這裏使用索引的方式傳入Set
也無法正確判斷
唯一的辦法是使用has()
時也傳入對應的索引
我們知道在JS中,複雜對象類型(Array、Object、Function、Set、Map等)在引用時都是使用數據保存在內存棧中的指針索引,而原始數據保存在內存堆中,所以在比較時都是
直接比較索引,這就導致無法直接用索引去與原始數據比較。
所以我們可以使用JSON.parse()
配合JSON.stringify()
來將索引轉爲原始數據來進行比較,以下是經過改進的代碼。
//交集
const intersection = (a, b) => {
let aa = new Set([...a].map(i => JSON.stringify(i)));
let bb = new Set([...b].map(i => JSON.stringify(i)));
return Array.from(
new Set([...aa].filter(x => bb.has(x)).map(i => JSON.parse(i)))
);
};
//並集
const union = (a, b) =>
Array.from(
new Set([
...[...a].map(i => JSON.stringify(i)),
...[...b].map(i => JSON.stringify(i))
])
).map(i => JSON.parse(i));