iT邦幫忙

2022 iThome 鐵人賽

DAY 5
1
Modern Web

Have fun! 新手也能打造的Javascript微型專案系列 第 5

Have fun! 新手也能打造的Javascript微型專案! Day5: 休息一下! 來個javascript陣列應用大補帖!

  • 分享至 

  • xImage
  •  
tags: ItIron2022 Javascript

前言

在進入之後的微型專案之前,我們先來個陣列練習吧! 陣列在幾乎所有的專案中都有著一席之地,其中很多常見的操作都可以透過es6之後的一些語法簡單的達成,今天讓我們扮演著面對不講理客戶的工程師,一一解決他對一些陣列操作的要求吧!

預期成果

今天我們預計完成以下幾個陣列的操作

  • 陣列的複製
  • 陣列的排序
  • 陣列的連接
  • 統計陣列內出現的元素次數

Getting started

陣列的複製

先從基本一點的東西開始吧,今天客戶給你了以下的陣列,同時千交代萬交代你在做後續的操作時不要影響到原本的陣列,否則要給你好看! 為了不激怒客戶,我們只好想各種辦法來進行陣列的複製。

// 以下為原始陣列
const arr = ['Danny', 'Mike', 'John', 'John', 'Tao', 'John', 'Mike']

// 請建立一個result陣列,有著與arr陣列完全相同的值與排序
// your code here

這算是實務上很常見的情境,有非常多種方法足夠讓你切入這個問題,我們先來張防雷圖讓你思考一下,等等就簡單帶過幾個常見方法。

防雷圖

  1. 不變應萬變,迴圈硬幹

我不能說你錯,這確實是一種可行的方法,先宣告一個空陣列接著利用迴圈一個一個推進該陣列中,可以!

const result = [];
for (let i = 0; i < arr.length; i++) {
    result.push(arr[i]);
}
  1. slice切切切,眼淚流流流

另一種方法是利用Array.slice方法,直接從頭切到尾,最終會產生一個複製後的陣列

const result = arr.slice();

當slice方法不傳遞任何參數進去時便會預設從頭切到尾,也就是整個陣列的值。

  1. 我很潮,我是擴展運算子

接下來這個可說是我最常用的方法了,es6新增的擴展運算子無論在陣列或物件上都有相當廣的應用範圍,其中複製值的部分非常實用

const result = [...arr];

以上提供了三種可能的複製陣列方法,而手段遠遠不止這一些,不過只要有這些武器應該夠你用了!
值得注意的是這些方法全部都是所謂的淺拷貝,深淺拷貝的差異請參考我去年的文章,剛好是該篇的主題。

陣列的排序

現在複製完畢了,客戶要求我們對這個新的result陣列進行排序,他希望讓這個陣列按照英文字母序排序(sort alphabetically)! 你也許會想說,簡單! javascript陣列本來就有個sort方法嘛! 而且照預設,sort的排序會將陣列內的元素轉為字串後對照unicode並按照對應的值進行排序,也就剛好符合字母排序的要求,這樣寫應該就行了吧!

const sortedResult = result.sort()

正當你洋洋得意時,客戶轉頭過來跟你說『啊!抱歉,要排序的是這個陣列才對,那就麻煩你囉!

const newArr = [{name: 'Danny'}, {name: 'Mike'}, {name: 'John'}, {name: 'John'},{name: 'Tao'}, {name: 'John'}, {name: 'Mike'}]

shocked face

你忍著想灌他一拳的念頭開始思考,好在sort是可以傳入所謂的comparison function,也就是一個函數讓sort知道你想怎麼樣去做排序,比方說今天你想從小排到大,那麼最常見的寫法便是

const demo = [10, 1, 2]
console.log(demo.sort((a, b) => a - b)) // [1, 2, 10] 

上述程式碼會有效是因為它會以裡面的comparison function回傳的結果作為如何排序的標準,一次會比較兩個數字a & b,而根據回傳的值會有以下的操作

  • 若回傳的值小於0,將a排在b之前。
  • 若回傳的值大於0,將a排在b之後。
  • 若回傳的值等於0,則不將兩者位置做任何改變。

理解這一點之後,要完成客戶的要求也就不是這麼困難囉! 跟範例唯一的差別在於字串不能用"-"運算符去做運算產生回傳值,因此我們需要麻煩一點,三個case都要手動處理到。

const newArr = [{name: 'Danny'}, {name: 'Mike'}, {name: 'John'}, {name: 'John'},{name: 'Tao'}, {name: 'John'}, {name: 'Mike'}]

newArr.sort((a, b) => {
  // 若a.name在排序上大於b.name,將a往後移
  if (a.name > b.name) {
     return 1
  // 若a.name在排序上小於b.name,將a往前移   
  } else if (a.name < b.name) {
     return -1
  }
  // 除此之外的case,回傳0維持原排序
  return 0
})

陣列的連接

解決完這個問題後,客戶馬上有了新的要求,說是現在突然拿到一份新的名單,要你將這兩份名單連接在一起組成新的陣列給他,新的資料要在舊的資料後,於是你又繼續埋頭苦幹了。

const oldList = ['Danny', 'Mike', 'John', 'John', 'Tao', 'John', 'Mike']

const newList = ['Mary', 'Mike', 'Joyce', 'Joyce', 'Mary']

好在這次的要求相當簡單,我們同樣有很多方法可以使用

  1. 不變應萬變,迴圈硬幹

一樣我們可以宣告一個新的陣列,而這個新陣列會是oldList的複製品,接著我們在用迴圈跑newList陣列一個一個元素推進去就行囉!

const result = [...oldList]

for (let i = 0; i < newList.length; i++) {
    result.push(newList[i])
}
  1. concat語法接一接

另一個選擇則是陣列原生的方法concat,也可以輕鬆地將兩個陣列連接在一起。

const result = [...oldList].concat(newList)
  1. 我很潮,我是擴展運算子

是的,看到前面的複製時我想你應該心裡有底了,實際上用擴展運算子複製兩個陣列再連接就行囉!

const result = [...oldList, ...newList]

統計陣列內出現的元素次數

終於到了今天最後一個要求了,在剛剛的陣列連接完成後,客戶又要一個新的資料,他希望你能替他統計陣列中每個名字出現的次數,最終以物件的方式展示結果

const list = ['Danny', 'Mike', 'John', 'John', 'Tao', 'John', 'Mike', 'Mary', 'Mike', 'Joyce', 'Joyce', 'Mary']

這個需求就讓你有點傷腦筋了,你當然可以用迴圈配合預先建立一個空物件,然後檢查該名字是否已經在物件中,若有的話則令次數加1,沒有的話則將該名字加入物件並令次數為1,不過你現在趕著下班,希望可以用一串程式碼就直接搞定,因此你想到了es6的新語法reduce!

const countResult = list.reduce((obj,item)=>{
  if (item in obj) {
    obj[item]++
  } else {
    obj[item] = 1
  }
  return obj
},{})

最終的輸出結果也與你想的相同! 於是你就高高興興的下班了! 留下一臉矇逼的客戶與讀者

result

不過別擔心,這個統計的方法可以參照這篇文章,有非常詳細的說明

總結

我們今天稍微休息了一下! 講了幾個陣列在實務上都很常見的應用方法,同時簡單的帶過reduce這個你可能有些陌生的語法,希望經過這幾個練習有讓你對於陣列的操作更上手一些,明天開始又會繼續新的微型專案開發囉! 接著,馬上進入我們今天的轉職Q & A環節吧!

轉職Q & A

Danny, 我目前已經開始在某某bootcamp開始上課,不過我總是很擔心自己學的不夠多,你有推薦什麼網路資源讓我能做額外的練習嗎?

很好的問題,網路上的免費/付費資源確實相當的多,完全到了令人眼花撩亂的地步,一開始會有些難以下手是很正常的,一般來說我會推薦幾個免費網站讓初學者去做練習.

通常我最先推薦的一定是這個免費課程,一共有30個小型專案,影片時間都不算太長,許多專案也做起來相當有趣,也是我這次鐵人賽主題選擇的靈感。

一個新手/高手都能把玩刷題網站,比起leetcode,在題目上更加有趣一些,可以藉由解題的過程增加你對於js的熟練度.

超級知名的教學網站,在youtube上也有非常多他們頻道的教學影片,每個你想學的主題都會有大量的練習可以做.

一般來說初學階段這樣就夠了,如果你想要更有系統性一點的話,可以在youtube上搜尋javascript tutorial之類的關鍵字,或是直接在特價時去udemy買個課程來上,真的不用怕沒有東西可以學,程式的水極深! 唯一我的建議會是,永遠都不要只看影片或文字教學,拜託拜託你一定要動手實作,不然你永遠都脫離不了所謂的教學影片地獄(tutorial hell),看再多教學都比不上你實際動手寫幾行code。

本文章同步發布於個人部落格,有興趣的朋友也可以來逛逛~!


上一篇
Have fun! 新手也能打造的Javascript微型專案! Day4: 寫個Chrome Extension定期發送通知,讓你養成喝水的好習慣吧!
下一篇
Have fun! 新手也能打造的Javascript微型專案! Day6: 老是算錢算不清,寫個簡單的計算機用用吧!(上)
系列文
Have fun! 新手也能打造的Javascript微型專案30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言