如何利用SET & FILTER去除陣列中重複的物件:進一步認識Set

前言

我在之前練習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的話,第一次遇上時還真的會有些手足無措~!很慶幸後來找到方法去解決,希望也能幫上有類似困擾的人!

參考文章

ES6入門
JavaScript取出”陣列-物件“重複/不重複值的方法
MDN-set

廣告

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s