iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 12
0
自我挑戰組

花三十天找到 JavaScript 沙漠中的綠洲系列 第 12

12 陣列補充

前言

嗨大家好,昨天的練習應該不難。請看下面的解答:

//第一題:請問下面 console.log 會出現哪個顏色?
let color = ["red","green","blue"];
console.log(color[2]); //答案是藍色

//第二題:承上,我要怎麼取出紅色?
color[0] //可用 console.log(color[0]); 檢查

//第三題:我想要新增橘色,變成陣列的第四筆資料,要怎麼寫?
color.push("orange"); //可用 console.log(color); 檢查

//第四題:我發現我打錯了,第四筆資料應該是黃色才對,請問我要怎樣把第四筆資料改成黃色?
color[3] = "yellow"; //可用 console.log(color); 檢查

//第五題:我懶得數 color 裡有幾筆資料,我要怎麼打,讓電腦自動告訴我答案?
color.length; //可用 console.log(color.length); 檢查

今天我們要補充一些昨天還沒講到的知識(你也可以把它當成咒語),那現在就跟我一起出發吧!

咒語一: unshift

有時候我想要讓陣列的前面新增一筆或多筆資料,這個時候就可以使用 陣列名 + .unshift(要加到陣列的東西1,要加到陣列的東西2,...) 。寫法如下:

let ary = [1,2,3];
ary.unshift("數字要開始囉",0);
console.log(ary); //印出["數字要開始囉",0,1,2,3]

咒語二: reverse

當我想要讓陣列裡的第一筆資料變成最後一筆資料,最後一筆資料變成第一筆資料時,不需要人工作業,可以直接使用 陣列名 + .reverse 解決。寫法如下:

let ary = [1,2,3];
ary.reverse();
console.log(ary); //印出[3, 2, 1]

到這裡為止應該都很簡單吧!相信你一定用過 excel ,下面幾個咒語跟 excel 的功能有些類似。我們還剩三個咒語,加油!

咒語三: sort()

當陣列裡的數字亂七八糟,想讓數字們從小排到大,或從大排到小嗎? 你需要這樣寫:

  • 大到小: 陣列名 + .sort(function(參數一,參數二){return 參數二 - 參數一;})
  • 小到大: 陣列名 + .sort(function(參數一,參數二){return 參數一 - 參數二;})

你可以自行命名參數的名字。我知道這樣很難記住,所以來實際寫寫看吧!

let arr = [2,3,4,1,5,6,7];

//從大排到小
arr.sort(function(x,y){
    return y-x;
});
console.log(arr); //印出[7, 6, 5, 4, 3, 2, 1]

//從小排到大
arr.sort(function(x,y){
    return x-y;
}); 
console.log(arr); //印出[1, 2, 3, 4, 5, 6, 7]

-----2021/02/09 補充-----
sort 的特性是從每個值的最左邊開始比較,能重新將陣列與物件排序。什麼意思呢?舉例來說如果一個陣列是這樣:array = [1,2,10,15,3],那單純只打 array.sort(); 會得到 [1, 10, 15, 2, 3] 。因為 [1,2,10,15,3] 這五個值的最左邊分別是 1、2、1、1、3 ,導致 10 跟 15 反而排到 2 和 3 前面。為此如果要讓陣列裡的數字,以數字大小來排列時,才需要如上所說的動點小手腳(?):

//從小排到大
array.sort(function(a, b) {
  return a - b; 
});
//從大排到小
array.sort(function(a, b) {
  return b - a; 
});

咒語四: filter()

當你想從陣列中挑出某些符合條件的資料,就可以使用 filter(function(參數)){ return + 條件} 。實際範例如下:

let arr = [2,3,4,5,6,7];
let arrLower5 = arr.filter(function(e){
    return e<5;  //回傳小於5的參數
}); 

console.log(arrLower5); //印出[2, 3, 4]

會宣告 arrLower5 這個變數,是因為要讓它印出,如果單純把 console.log 寫在 return 下面,不會被執行。但是把 console.log(e) 放到函式外面,會得到 e is not defined 。因此給它一個名字,再用 console.log 把它印出來。

咒語五: indexOf()

最後我們來看 indexOf() 。這句話會回傳在陣列裡符合條件,並且第一筆被找到的資料在陣列裡的哪個位置。如果陣列裡都找不到,則會回傳 -1 。寫法為: 陣列名 + .indexOf(要查找的資料)

let arr = ["A","B","C","D"];
console.log(arr.indexOf("A")); //印出0

舉例來說,在上面的例子中,當我想要找 A 這筆資料,可以把它放進 indexOf 後面的括號,因為它是字串,所以還要額外加上雙引號。 console.log 則會印出它在第 0 個位置,注意!陣列的第 0 個位置,其實是第一筆資料。

同時,我也可以設定說我要從第幾筆開始查找,只要在本來的例句後面加上逗號,標註第幾位即可:陣列名 + .indexOf(要查找的資料,第幾個位置開始查)

let arr = ["A","B","C","D","B","C","B"];
console.log(arr.indexOf("B",3)); //印出4
console.log(arr.indexOf("B",4)); //還是印出4
console.log(arr.indexOf("B",5)); //印出6
console.log(arr.indexOf("D",5)); //印出-1

上面的範例中,共有四個 console.log 。第一題要從第 3 個位置開始找 B ,也就是從 ["D","B","C","B"] 中去尋找,找到的第一個 B 位在["A","B","C","D","B","C","B"] 的第 4 個位置(第五筆資料),因此印出 4 。第二題從第 4 個位置開始找,,也就是從 ["B","C","B"] 中尋找,因此還是印出 4 。第三題應該不用再解釋,會印出 6 。至於第四題,因為第 5 個位置開始,找不到 D 了,所以印出 -1 。

-----2021/02/09 補充-----
使用 indexOf 尋找陣列中包了陣列的值時,發現就算明明有那個值,卻找不到東西。這才發現我對於 indexOf 的了解還不夠扎實,在此也補充一下觀念。

舉例來說,當我有一堆資料 arr = [[3,0],[1,2],[5,0],[10,3]],想從裡面找到 [3,0] 在 arr 的第幾個位置,直接使用 arr.indexOf("[3,0]") 會找不到並得到 -1 ,但裡面明明有這個值啊!

其實這是因為 indexOf 是用嚴格模式 (===) 判斷,而陣列是物件的一種,比較物件時,只有當這兩個物件的內容物完全相同才會得到 true ,不然即使其中有幾個值相同也會得到 false 。

那麼要怎麼解決呢?可以自己用 for 迴圈寫一個客製化 indexOf 函式。

function indexOfCustom (parentArray, searchElement) {
        for (let i = 0; i < parentArray.length; i++ ) { 
            if ( parentArray[i][0] == searchElement[0] && parentArray[i][1] == searchElement[1] && parentArray[i][2] == searchElement[2] && parentArray[i][3] == searchElement[3]) { 
                return i;
            }
        }
        return -1;
    }

因為陣列是從0開始數,預設代表陣列位置的變數i=0。當i小於查找項目的長度,跑下面的迴圈,跑完加一再繼續跑,直到等於長度時停止。從查找陣列的第0項開始,當第0項陣列中的第0個位置的值,跟要找的陣列的第0個值相同,就讓i顯示0返回,藉此得知要找的就在第0的位置,依此類推,若都找不到則返回-1。parentArray[i][0] == searchElement[0] 這裡要寫多少個,則端看你的 searchElement 陣列中有幾個值。

其實陣列還有很多很多能玩的,沒有辦法一一介紹,有興趣或是在實際應用中遇到的時候,可以再呼叫 Google 神燈精靈出來幫忙唷!

-----2021/02/24 補充-----
若要複製陣列,再進行 sort 等動作,以免動到原始陣列,可以使用[...陣列名]。例如:

let arr = [1,3,2];
let arrCopy = [...arr];
console.log(arrCopy); //確認複製有成功
arrCopy = arrCopy.sort();
console.log(arrCopy); //複製的印出 [1,2,3]
console.log(arr); //原本的仍印出 [1,3,2]

如果直接指定 let arrCopy = arr ,在做 sort() 時會發現原本的也被動到了:

let arr = [1,3,2];
let arrCopy = arr;
console.log(arrCopy); //確認複製有成功
arrCopy = arrCopy.sort();
console.log(arrCopy); //複製的印出 [1,2,3]
console.log(arr); //原本的也跟著印出 [1,2,3],失去複製的意義

學習與參考資料

JS 學徒特訓班教學影片及練習題 22-23 + 27 關
JavaScript 陣列處理方法 [filter(), find(), forEach(), map(), every(), some(), reduce()]:https://wcc723.github.io/javascript/2017/06/29/es6-native-array/#Array-prototype-filter
Array.prototype.indexOf(): https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
Javascript indexOf for an array of arrays not finding array: https://stackoverflow.com/questions/10260165/javascript-indexof-for-an-array-of-arrays-not-finding-array


上一篇
11 物件與陣列
下一篇
13 forEach
系列文
花三十天找到 JavaScript 沙漠中的綠洲35
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言