將陣列裡面物件的一樣屬性整理一起


Posted by backas36 on 2021-07-31

這篇是為了紀錄 Lidemy 程式導師實驗計畫第五期的期中考 我想好久還是沒過關的題目

原始資料:

[
  {author:aaa, bookTitle:'bookA'},
  {author:bbb, bookTitle:'bookB'},
  {author:aaa, bookTItle:'bookC'},
  {author:aaa, bookTitle:'bookD'},
  {author:bbb, bookTitle:'bookE'},
  {author:ccc, bookTitle:'bookF'},
]

將原始資料,改成這樣 :

[
  {author:aaa, bookTitle:['bookA', 'bookC', 'bookD']},
  {author:bbb, bookTitle:'bookB', 'bookE'},
  {author:ccc, bookTitle:'bookF'}
]
  1. 將一樣 author 的 bookTitle 整理成陣列
  2. 要確定作者出現的順序與bookTitle順序要跟原始資料一樣

1)


const data = [
  {author:'aaa', bookTitle:'bookA'},
  {author:'bbb', bookTitle:'bookB'},
  {author:'aaa', bookTitle:'bookC'},
  {author:'aaa', bookTitle:'bookD'},
  {author:'bbb', bookTitle:'bookE'},
  {author:'ccc', bookTitle:'bookF'},
]

  const result = []

  const uniqueAuthor = []
  for(let i =0 ; i < data.length; i++){
    if(!uniqueAuthor.some(x => x=== data[i].author)){
      uniqueAuthor.push(data[i].author)
    }
  }

  for(let i =0; i< uniqueAuthor.length;i++){
    let authorArr = data.filter(el => el.author === uniqueAuthor[i])
    let titleArr = authorArr.map(el=> el.bookTitle)
    result.push({
      author:uniqueAuthor[i],
      bookTitle:titleArr.length >1 ? titleArr:titleArr[0]
    })
  }
  console.log(result)

先解釋這段

  const uniqueAuthor = []
  for(let i =0 ; i < data.length; i++){
    if(!uniqueAuthor.some(x => x=== data[i].author)){
      uniqueAuthor.push(data[i].author)
    }
  }

這段是利用 some (some 為陣列中是否至少有一個元素) ,將 author 整理成陣列放入uniqueAuthor,讓 author 沒有重複

這邊其實也可以利用 Set 或者其他 method 改寫,( 功力太弱,一開始都把題目想得很複雜,自以為很帥的想一堆 method 來解決問題! )

總之,第一步一定要先解決 author 重複的狀況,所以想辦法把 author 改成都沒有重複的形式,就好解決了。

例如利用 Set :

 const uniqueAuthor = [...new Set(data.map(book => book.author))]

再來解釋這段


  for(let i =0; i< uniqueAuthor.length;i++){
    let authorArr = data.filter(el => el.author === uniqueAuthor[i])
    let titleArr = authorArr.map(el=> el.bookTitle)
    result.push({
      author:uniqueAuthor[i],
      bookTitle:titleArr.length >1 ? titleArr:titleArr[0]
    })
  }

先利用 filter 將一樣 author 的資料整理成陣列放到 author 中。
這時候去 console 的話會得到這樣的結果
[ { author: 'aaa', bookTitle: 'bookA' }, { author: 'aaa', bookTitle: 'bookC' }, { author: 'aaa', bookTitle: 'bookD' } ] [ { author: 'bbb', bookTitle: 'bookB' }, { author: 'bbb', bookTitle: 'bookE' } ] [ { author: 'ccc', bookTitle: 'bookF' } ]

接著再將 bookTitle 整理成陣列,讓 titleArr 變成這樣

[ 'bookA', 'bookC', 'bookD' ]
[ 'bookB', 'bookE' ]
[ 'bookF' ]

確定這兩個步驟都 OK , 然後再將它們組合起來 push 到 result

result.push({
      author:uniqueAuthor[i],
      bookTitle:titleArr.length >1 ? titleArr:titleArr[0]
    })

解決這題目的方式其實很多種,在這邊我只列出我實際練習過的形式出來,但是思路上其實都大同小異,最難的還是再怎麼將心中的步驟用程式去實現出來。

後來老師有提供解答,我覺得很適合讓我清楚整個解題的邏輯,在這邊列出老師提供的解決方式 :

2)

let result = []
for(let i = 0; i < data.length; i++){
  const currentData = data[i]
  const index = result.findIndex(book => book.author === currentData.author)
  if(index >= 0){
    if(!Array.isArray(result[index].bookTitle)){
      result[index].bookTitle = [result[index].bookTitle]
    }
    result[index].bookTitle.push(currentData.bookTitle)
  } else {
    result.push(currentData)
  }
}
console.log(result)

首先是利用 findIndex 找尋 result 陣列中與currentData 一樣 author 的 index ,如果沒找到會回傳 -1。

如果回傳 -1 ,會將 currentData 新增到 result 中。

假設有找到,就會先確定此時 result 中的 bookTitle 是不是陣列,如果不是就轉換成陣列,然後將新的 bookTitle 新增到到這陣列中。


如果覺得解釋得不夠清楚的話,可以建議每個步驟都去 console 出來,應該就會比較清楚每一步驟在幹什麼,這部分真的不是很好懂。
也謝謝老師提供了這個題目讓我清楚我哪邊需要再加強,還有其實好多同學都有不一樣的解法(覺得厲害👍🏽 ),每個人思考方式不一樣,這是一定的,怎麼實現、怎麼正確的呈現才是重要的。


#javascript #Array #object







Related Posts

[week 1] 版本控制 - Git 進階指令 & GitHub

[week 1] 版本控制 - Git 進階指令 & GitHub

漏洞與修補留言板 XSS 和 SQL Injection

漏洞與修補留言板 XSS 和 SQL Injection

再次部署在 Heroku 的問題紀錄

再次部署在 Heroku 的問題紀錄


Comments