實用陣列操作大全-基礎篇


陣列可以被視為是一種特別的「物件」,和物件一樣,是零到多個屬性的集合,而且沒限制甚麼東西不能放進去,所以陣列裡面可以是字串、數字等基本型別,也可以是物件、函式,甚至是另一個陣列。

而陣列與物件的差別在於,陣列是有順序的集合,能夠透過中括號[]加上索引來存取。也因為這種特性,所以陣列有許多的方法可以使用。


圖片來源:codingyuri

這次就來談談如何運用陣列的基本方法:

Array.prototype.push()

使用 push() 方法可以在陣列尾端新增一個值。
push() 方法回傳的值為陣列長度

這一天有一塊巨大的隕石往地球飛來,超級英雄們緊急集合,要把隕石推出太陽系,但是隕石太大顆,所以又找了驚奇隊長來幫忙。

let array = ['鋼鐵人','美國隊長','浩克','雷神']
let value = array.push('驚奇隊長');
console.log(array); 
//['鋼鐵人', '美國隊長', '浩克', '雷神', '驚奇隊長']
console.log(value);
// 5

push() 適用的在類似搶頭香的情境中。

Array.prototype.unshift()

使用 unshift() 可以在把想要新增的元素插入在陣列第一個元素的位置,也就是 index 為 0 的位置。
unshift() 回傳的值也是陣列長度

let array = ['鋼鐵人','美國隊長','浩克','雷神']
let value = array.unshift('黑寡婦');
console.log(array); 
//['黑寡婦', '鋼鐵人', '美國隊長', '浩克', '雷神']
console.log(array[0]);
//'黑寡婦'
console.log(value);
// 5

unshift() 則適用於新聞類的排序,越新的新聞排到越前面。

Array.prototype.pop()

如果要把陣列尾端的元素刪除,可以使用 pop() 方法。
pop() 方法回傳的值為被刪除的元素。

let array = ['鋼鐵人','美國隊長','浩克','雷神']
let value = array.pop();
console.log(array); 
//['鋼鐵人', '美國隊長', '浩克', ]
console.log(value);
// '雷神'

pop 是取自 Popping 這個單字,意思是彈出。不是流行音樂的意思。

Array.prototype.shift()

如果要把陣列第一個元素刪除,可以使用 shift() 方法。
shift() 方法回傳的值為被刪除的元素。

let array = ['鋼鐵人','美國隊長','浩克','雷神']
let value = array.shift();
console.log(array); 
//['美國隊長', '浩克', '雷神']
//array[0]的鋼鐵人被刪除了
console.log(value);
// '鋼鐵人'

Array.prototype.splice

splice()可以刪除指定位置的陣列元素,或新增指定位置的陣列元素。
回傳一個新的陣列,裡面放著被刪除的元素

array.splice(startIndex[, deleteCount[, item1[, item2[, ...]]]])
  1. startIndex :要開始修改的索引位置。
  2. deleteCount :要刪除的元素數量(從startIndex位置的原四開始算)。
  3. item1,item2… :新增的元素,由startIndex開始新增。這個選項可以選擇性使用。

來個情境題:這一天復仇者聯盟的超級英雄們舉辦派對,結果不小心混入了兩個正義聯盟的英雄,請問要如何把他們找出來,並且叫一台車把他們裝在一起送回家?

let array = ['鋼鐵人','蜘蛛人','超人','蝙蝠俠','浩克','雷神'];
let newArray = array.splice(2,2);
console.log(array);
//['鋼鐵人', '蜘蛛人', '浩克', '雷神']
console.log(newArray);
//['超人', '蝙蝠俠']

原本由超人與蝙蝠俠占用的名額由’驚奇隊長’跟’緋紅女巫’來代表。

let array = ['鋼鐵人','蜘蛛人','浩克','雷神'];
let newArray = array.splice(2,0,'驚奇隊長','緋紅女巫');
console.log(array);
//['鋼鐵人', '蜘蛛人', '驚奇隊長', '緋紅女巫', '浩克', '雷神']
console.log(newArray);
//[]回傳空陣列

Array.prototype.sort()

MDN上的解釋:

來看一下MDN上關於sort()的解說:
sort() 方法會原地(in place)對一個陣列的所有元素進行排序,並回傳此陣列。排序不一定是穩定的(stable)。預設的排序順序是根據字串的 Unicode 編碼位置(code points)而定。

什麼?根據 Unicode 編碼位置(code points)來決定順序,這是甚麼東西?

來看看MDN上的範例:

const months = ['March', 'Jan', 'Feb', 'Dec'];
months.sort();
console.log(months);
// expected output: Array ["Dec", "Feb", "Jan", "March"]

const array1 = [1, 30, 4, 21, 100000];
array1.sort();
console.log(array1);
// expected output: Array [1, 100000, 21, 30, 4]

不是由大到小,也不是由小到大,這實在是讓人一頭霧水呀???

MDN上面sort()方法的撰寫規則如下:

arr.sort([compareFunction])

也就是說如果你沒用一個判別大小的函式來做判斷,才會使用Unicode 編碼位置(code points)來決定順序。

如果你真的像要為數字排大小(當比較的是數字的時候),可以寫一個函式來判別:

var numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {
  if (a > b) return 1;
  if (a < b) return -1;
  return 0;
});
console.log(numbers); // [1, 2, 3, 4, 5]

上面的判斷式也就是把陣列元素一一拿來當作a與b兩個參數,傳入判斷式做比較:

  • 如果回傳的值小於 0,則 a 的索引位置比 b 的小,也就是 a 在 b 前面。
  • 如果回傳的值大於 0,則 b 的索引位置 比 b 的大,也就是 a 在 b 後面。
  • 如果等於 0,則 a 與 b 的位置不會改變,但會與陣列其他元素繼續比較。

至於是陣列索引小的當a,還是大的當a,則倚賴個瀏覽器廠商的實作。

compareFunction要更簡潔一些,可以這樣寫:

var numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {
  return a - b;
});
console.log(numbers);

// [1, 2, 3, 4, 5]

MDN也寫了:由於依賴執行環境的實作,所以並不能保證排序的時間及空間複雜度。

也就是,sort() 這個方法,每家瀏覽器背後運作的原理都不相同。

像是Chrome瀏覽器,一般是使用快速排序法( Quick Sort ),但是在陣列裡面的元素小於10的時候是使用插入排序法( Insertion Sort),還使用了二分搜尋法 Binary Search 來優化排序。( 詳細說明可以參考: 淺談 JS sort() 到背後排序方法 )

我認為 sort() 是可以深入再研究的一個陣列方法,但是身為一個陣列大全,就先點到為止。

Array.prototype.indexOf()

MDN上的解釋:

回傳給定元素於陣列中第一個被找到之索引位置,若不存在於陣列中則回傳 -1。
適合用來確認陣列中那個元素是否存在。

array.indexOf(searchElement,fromIndex)
  • searchElement:要找的元素。
  • fromIndex:要從第幾個元素開始找,預設為0。這個參數可以不設。
let array = ['鋼鐵人','蜘蛛人','浩克','雷神','鋼鐵人'];
let value = array.indexOf('浩克');
console.log(value);
// 2
let value1 = array.indexOf('鋼鐵人',2)
console.log(value1);
// 4 因為是從 [2] 的浩克開始往後面找。
let value2 = array.indexOf('美國隊長');
console.log(value2);
// -1  美國隊長沒有在陣列中

Array.prototype.lastIndexOf()

MDN上的解釋:

回傳給定元素於陣列中最後一個被找到之索引,若不存在於陣列中則回傳 -1。
搜尋的方向為由陣列尾部向後(即向前)尋找,啟始於 fromIndex。

let array = ['鋼鐵人','蜘蛛人','浩克','雷神','鋼鐵人'];
let value = array.lastIndexOf('浩克');
console.log(value);
// 2
let value1 = array.lastIndexOf('鋼鐵人',2)
console.log(value1);
// 0 因為是從'浩克'往前找,找到的'鋼鐵人'是在索引[0] 的位置
let value2 = array.lastIndexOf('美國隊長');
console.log(value2);
// -1

Array.prototype.prototype.findIndex()

MDN上的解釋:

findIndex()方法傳回陣列中滿足測試函式的第一個元素的索引。
如果沒找到對應元素就回傳 -1。

findIndex()與indexOf()相似,但是findIndex()可以帶入函式來判斷陣列中是否有滿足函式條件的元素。

const avengers = [
    {
        name: '鋼鐵人',
        firePower: 10,
        bodyForce: 5
    },
    {
        name: '美國隊長',
        firePower: 5,
        bodyForce: 8
    },
    {
        name: '浩克',
        firePower: 0,
        bodyForce: 10
    }
]
let isFirePower = function(element){
    return element.firePower === 5;
}
console.log(avengers.findIndex(isFirePower))
// 1

Array.prototype.reverse()

MDN上的解釋:

反轉(reverses)一個陣列。陣列中的第一個元素變為最後一個,而最後一個元素則變成第一個。
回傳的值為反轉的陣列本身。

let array = ['鋼鐵人','蜘蛛人','浩克','雷神'];
let newArray = array.reverse();
console.log(array);
//['雷神', '浩克', '蜘蛛人', '鋼鐵人']
console.log(newArray);
//['雷神', '浩克', '蜘蛛人', '鋼鐵人']

Array.join

會將陣列(或一個類陣列(array-like)物件)中所有的元素連接、合併成一個字串,並回傳這個字串。

arr.join([separator])
  • separator:用來隔開每個元素的字串,預設是英文逗號 (,) ,如果separator使用空字串的話,合併之後,元素之間不會有任何區隔。
let array = ['鋼鐵人','蜘蛛人','浩克','雷神'];
let newArray = array.join('*');
console.log(newArray);
//鋼鐵人*蜘蛛人*浩克*雷神

Array.prototype.concat

MDN上的解釋:

用來合併兩個或多個陣列。
不會改變現有的陣列,回傳一個包含呼叫者陣列本身的新陣列。

var new_array = old_array.concat(value1[, value2[, ...[, valueN]]])

範例:

let justice = ['超人','蝙蝠俠','神力女超人']
let avangers = ['鋼鐵人','蜘蛛人','浩克','雷神'];
let justiceAvangers = justice.concat(avangers);
console.log(justiceAvangers);
//['超人', '蝙蝠俠', '神力女超人', '蜘蛛人', '浩克', '雷神', '鋼鐵人']

也可以陣列合併字串:

let avengers = ['鋼鐵人','蜘蛛人','浩克','雷神'];
let newAvengers = avengers.concat('黑寡婦');
console.log(newAvengers);
//['鋼鐵人', '蜘蛛人', '浩克', '雷神', '黑寡婦']

Array.prototype.slice

MDN上的解釋:

取出起始索引到結束索引的元素,並回傳由取出元素所組成的新陣列。
原有陣列不會被修改

arr.slice([begin[, end]])
const avengers = ['鋼鐵人','蜘蛛人','浩克','雷神','奇異博士','黑豹'];
let newAvengers = avengers.slice(2,4);
console.log(newAvengers);
//['浩克', '雷神']

Array.prototype.includes()

includes() 方法會判斷陣列是否包含特定的元素,並以此來回傳 true 或 false。

const avengers = ['鋼鐵人','蜘蛛人','浩克','雷神','奇異博士','黑豹'];
console.log(avengers.includes('雷神')); //true
console.log(avengers.includes('黑寡婦')); //false

Array.prototype.toString()

MDN上的解釋:

toString() 方法將回傳一個可以表達該陣列及其元素的字串。
陣列的每個元素將被轉為字串,並以,連接,同時會回傳該字串。

const avengers = ['鋼鐵人','蜘蛛人','浩克','雷神'];
let newAvengers = avengers.toString();
console.log(newAvengers);
//"鋼鐵人,蜘蛛人,浩克,雷神"
//每個元素被轉為字串,並以逗號連接。

參考資料

-MDN : Array.prototype.sort
-從 Array 的 sort 方法,聊到各瀏覽器的實作,沒想到 Chrome 和FireFox 的排序如此不同
-淺談 JS sort() 到背後排序方法


實用陣列操作大全-基礎篇
https://popeye-ux.github.io/2021/11/16/arrayBasic/
作者
POPEYE
發布於
2021年11月16日
許可協議