基礎javascript!利用reduce統計一個陣列中各元素出現的次數!

前言

我已經好一段時間沒有寫技術文章了..即使是簡單的也沒寫,最近幾乎都是在做超小專案的練習紀錄。不過這幾天花了不少時間在處理AC同學的問題,其中有個同學就提問如何做陣列內不同元素的統計,我回應他的方法是我自己在專案開發時很常使用的做法,但仔細看下來會發現要與人解釋這個邏輯還真~需要費一點功夫,為了不浪費平台的版面,我乾脆直接寫一篇文章做簡單的紀錄。

reduce for beginner

Array.reduce是ES6之後推出的陣列新語法,主要用途是在加總陣列的總和。
基本語法如下 array.reduce(callback,初始值) 若初始值沒給則預設為0。
其中callback包含四個參數,(目前總值,當前的元素值,當前的index,當前的array),而每一次callback的回傳值就是下一次的目前總值,我們看一下簡單的範例

const arr = [1,5,7,2,3]
const result = arr.reduce((a,b)=>a + b))
console.log(result) // 18

你他媽最好有初學者有辦法看懂這鬼東西啦!!!!

所以我決定試著用另一個說法說明reduce,一般來說我們常見的reduce會寫成以下的格式

const arr = [1,5,7,2,3]
const arr.reduce((a,b)=>{
  return a + b
},0)

我們一個一個部分拆開來看,reduce內碰到的第一個括號其實是一個匿名函數,它接收兩個參數,你可以理解成第一個參數是目前的加總總值第二個則是目前跑到的元素,而每次的加總總值就是你回傳的結果,最後面逗號後面的0則是你加總的起始點。我知道沒人聽得懂我在說啥,所以實際看一下上面的例子會如何運行吧!

跑到第一個元素 1的時候

此時的a為0(加總的起點),b就是目前跑到的1 
回傳 a + b 就是 0 + 1 = 1,將這個加總結果作為新的總值繼續往下跑

跑到第二個元素 5的時候

此時的a為1(就是剛剛加總出來的新總值),b為目前跑到的5
回傳 a + b 就是 1 + 5 = 6,將這個加總結果作為新的總值繼續往下跑

跑到第三個元素 7的時候

此時的a為6(就是剛剛加總出來的新總值),b為目前跑到的7
回傳 a + b 就是 6 + 7 = 13,將這個加總結果作為新的總值繼續往下跑

這樣以此類推跑完陣列之後,最終的值就是18,也就是整個陣列的加總結果。

如何利用reduce統計陣列內不同元素出現的次數?

現在你比較了解reduce的用法了,那我要如何用reduce去統計陣列內的元素出現次數呢?
我們先看一下解答,我再從解答做說明。

const names = ['Danny','Danny','Jack','Sam','Danny']
const total_count = names.reduce((obj,item)=>{
  if (item in obj) {
    obj[item]++
  } else {
    obj[item] = 1
  }
  return obj
},{})

console.log(total_count) 
// 輸出結果
{Danny: 3, Jack: 1, Sam: 1}

這次的reduce中間又發生了什麼事情呢,首先我們要注意幾個地方

  • 我們這次的起點不是0,而是一個空物件{ }
  • 在條件式的部分使用了in ,這是一個檢查物件內是否有指定屬性的方法,如以下示範
const demo = {
   name:'Danny',
   id:'9831032'
}

'name' in demo // true
'id'   in demo // true
'age'  in demo // false

瞭解這兩個部分之後,剩下的東西就不困難囉,我們一樣一個一個元素來看

跑到第一個元素 ‘Danny’的時候

此時的obj為一個空物件{}(加總的起點),item就是目前跑到的'Danny'
由於obj是個空物件,自然沒有'Danny'這個屬性,所以條件式的部分我們就會跑else內的程式碼,令obj['Danny'] = 1
最後再回傳obj作為新的總值,因為我們希望利用這個物件去統計所有出現的元素次數
此時的obj內容為
{
  Danny:1
}

跑到第二個元素 ‘Danny’的時候

此時的obj為{ Danny:1 },item就是目前跑到的'Danny'
由於obj這次有'Danny'這個屬性,所以條件式的部分我們就會跑if內的程式碼
令obj['Danny']++
最後再回傳obj作為新的總值
此時的obj內容為
{ Danny:2 }

跑到第三個元素 ‘Jack’的時候

此時的obj為{ Danny:2 },item就是目前跑到的'Jack'
由於obj這次沒有'Jack'這個屬性,所以條件式的部分我們就會跑else內的程式碼
令obj['Jack'] = 1
最後再回傳obj作為新的總值
此時的obj內容為
{ Danny:2 ,Jack:1}

接著以此類推,最終就會看到我們一開始所見的輸出結果囉!

結語

reduce對初學者來說是個相當難懂的概念,官方文件裡面又一堆acc,curr之類的鬼東西,我記得我剛接觸時也是一個頭兩個大! 但用來做陣列內的元素統計又是一個極端實用的方法,熟練之後已經是我常用的小幫手了!希望這篇文章有幫助到為reduce所苦的孩子們~!

基礎javascript!利用reduce統計一個陣列中各元素出現的次數! 有 “ 8 則迴響 ”

  1. 請問obj[item] = 1 是什麼意思 ,
    obj初始值是{}空物件, 所以 變成 {} [‘Danny’] = 1 為什麼會變成 { Danny:1} 呢?

  2. Kevin你好~! 其實不用想的太複雜,你已經很接近真相了。obj確實初始值是個空物件,不過我相信你知道在物件中取值其實可以透過dot notion或是 bracket notation兩種方法
    const person = {
    name: ‘Danny’,
    age: 29
    }
    console.log(person.age) // 29
    console.log(person[‘name’]) // Danny
    console.log(person[‘id’]) // undefined ,該屬性不存在person物件

    所以同樣的,也可以利用這兩個方法將屬性加入物件
    person[‘id’] = 1 // 將id:1加入person物件
    此時person 為
    {
    name: ‘Danny’,
    age: 29,
    id: 1
    }

    所以當今天obj是個空物件,他自然不會有目前迭代到的’Danny’屬性,就可以利用
    obj[‘Danny’] = 1 將Danny屬性加入obj物件囉! 回覆時無法用程式碼回應,如果還是覺得很困惑的話,可以再繼續提問:D 我很樂意提出協助!

  3. 推 本來要只是要找網頁標籤元素次數
    結果學到更多 JS 的東西
    這個網站好讚 我是新手該從哪邊看起呢

  4. 大學生你好~! 這就要看你了,如果你的目標是了解三元素(HTML/CSS/JS)並練就比較紮實的能力,那其實我的blog並不合適,裡面的紀錄較為零散,很多都是我初學時邊學邊寫的文章,因此比較沒有系統性的整理。如果真想好好學習網頁開發的話,那我會建議你在網路上搜尋一些課程,你可以先去Udemy或是yt找一些特價、免費的課程試著學學看,試試水溫看自己是不是真的有興趣,真想繼續下去的話隨時歡迎你來詢問,我很樂意提供一些轉職的建議的:D

    1. 了解!我覺得網頁蠻有趣的,但要自己開發從無到有就不太擅長了,(可能是因為一支半解的狀態)
      轉職的建議 我還沒就業啦哈

      1. 轉職其實也泛指轉換跑道XD 比方說你學商的想學程式也行這樣~可以先去看看一些課程了解大致的原理,甚至打探一下目前就業市場的薪資情況來當作你要不要投入的參考,當然,你要當作興趣學是完全沒有問題的~!

發表迴響

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

WordPress.com 標誌

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

Twitter picture

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

Facebook照片

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

連結到 %s