前言
我在之前練習JS的時候曾經寫過一篇三種取出陣列不同元素的方式,在那之後我一直很習慣使用set去處理類似的問題,直到上周AC的作業中我發現當時介紹的方式並不完美,今天就來進一步的了解Set,以及如何處理作業中遇到的問題。
首先我們先來複習一下上次文章中對於set的介紹,試著看一下以下的程式碼並回答輸出的結果。
const arr = [1,2,5,7,7,10] console.log([...new Set(arr)]
相信這應該難不倒人,經過擴展運算子之後,輸出結果會是[1,2,5,7,10]的陣列,那看一下接下來的問題。
const obj1 = {} const obj2 = {} console.log([...new Set([ obj1 , obj2 ])])
也許你會認為相當容易,兩個都是空物件,set會回傳一個唯一的數組,答案應該是[ {} ]吧?
很可惜,實際跑一次你會發現事情並不如你所想,但為什麼?
How set works exactly?
實際上set這個建構子在確認裡面的成員是不是unique的時候,用的方法很類似所謂的嚴格相等(===),也就是1 & ‘1’ 會視為兩個不相同的元素。了解這點後相信你可以理解為什麼上述的問題中答案不如你預期了,沒錯,這會扯到我們之前提過的call by value/reference的問題,上方的例子中,由於本身obj1 & obj2占用不同的記憶區塊,自然被視為不相同的元素!
利用Set & filter去除陣列中重複的物件
現在你知道你不能用單純的set去將陣列中重複的物件排除了,我們需要配合filter使用,看一下以下的程式碼。
const obj1 = { name:'Danny', id:9831032 } const obj2 = { name:'Danny', id:9831032 } const set = new Set() const arr = [obj1,obj2] const result = arr.filter(item=>!set.has(item.name)?set.add(item.name):false) console.log(result) // [ { name: 'Danny', id: 9831032 } ]
一步步拆解以上的程式碼。
- 首先我們宣告了兩個值完全相同的物件obj1&obj2,並同時宣告了一個空new Set 和陣列arr
- 接著我們宣告了result變數用來儲存我們filter後的結果
- 當我們迭代陣列中的每個元素時,我們查看它的name值是否存在set內,如果沒有,我們利用set.add將那個name傳入set中。
- 上述步驟中我們用了set的兩個method:add & has,set.has會回傳一個boolean,add則會將argument加入set中。
- filter只會將判斷為true的值丟進result中,其中只有obj1通過,所以最後result的結果便只剩一個物件囉。
結語
這篇文章進一步介紹了如何處理陣列中的物件,以及set的屬性探討。這個方法在處理資料庫資料時尤其有效,有時候你撈出了一模一樣的餐廳資料,但你只想在樣板上顯示你評論過的餐廳數量而非被灌水過的結果。不夠理解set的話,第一次遇上時還真的會有些手足無措~!很慶幸後來找到方法去解決,希望也能幫上有類似困擾的人!
參考文章