iT邦幫忙

2022 iThome 鐵人賽

DAY 19
0
Modern Web

從新開始學習p5.js畫出一片天系列 第 19

D19_陣列資料操作[基本概念,資料排序]

  • 分享至 

  • xImage
  •  

陣列資料操作[基本概念,資料排序]

今天來整理一下陣列的各種操作技巧

陣列的基本操作
let arr = [1, 2, 3, 4];

陣列本身像是一個存放資料的容器,只是欄位名稱是以數字流水號來表示,
並以 0 為流水號的開始編號,因此常會聽到第0個元素,
像是 arr[0] -> 1, arr[1] -> 2

物件讀取欄位的資料,也可以採用陣列的讀取方式
let obj = {
firstName: "Jason",
lastName: "Lee",
age: 25
};

obj["firstName"] -> "Jason", obj["lastName"] -> "Lee"

陣列的操作,基本上分成幾種功能類型

  1. 資料存放類:新增,刪除,合併,分段
  2. 資料排序類
  3. 資料搜尋類
  4. 資料篩選類
  5. 資料逐筆處理類(迴圈模式 for)
  6. 資料格式轉換
  7. 資料檔案存取

資料存放類

const arr = [];
-> length: 0

arr[0] = "cat";
arr[2] = "dog";
console.log(arr);
console.log(arr[1]);

要設定陣列資料時,最好是按照流水號的順序設定,但是也可以不按流水號號碼順序設定
範例中,跳過流水號1,會使得 arr[1] 的資料為 empty,
陣列內容變成  ['cat', empty, 'dog'] ,陣列資料長度為 length: 3
查看 arr[1] 會得到 undefined,容易造成後續處理陣列資料時產生錯誤。

執行結果
執行結果

如果不是使用數字當流水號,而是用字串當流水號時,會被視為是加入了1個檔位名稱為 "a" 的物件資料,
在陣列的長度上並不列入計算,只會將以數字流水號的資料項目做為陣列長度的計算

const arr = [];
function setup() {
	console.log(arr);
	arr[0] = "cat";
	arr[1] = "bird";
	arr[2] = "dog";
	arr["3"] = "fish";
	arr["a"] = "lion";
	
	console.log(arr);  //- ['cat', 'bird', 'dog', 'fish', a: 'lion']
	console.log(arr[1]); //- bird
	console.log(arr[3]); //- fish
	console.log(arr["a"]); //- lion
	console.log(arr.length); //- 4
	console.log(arr["1"]); //- bird

	for(item of arr){
		console.log(item);
	}
	//-- cat, bird, dog, fish
}

經測試 arr["3"] = "fish"; 文字形態的數字做為流水號是可以的。
在將陣列資料逐筆印出時,會發現只有數字流水號的元素會印出來,
這個差異要特別注意,以免發生資料讀不到或是陣列資料長度錯誤。

如果想要直接增加陣列元素
arr.push("tiger");
會加在最後一個數字流水號的下一個編號,
console.log(arr);
結果為 (5) ['cat', 'bird', 'dog', 'fish', 'tiger', a: 'lion']

想到一些奇怪的設定,也來確認一下

arr["05"] = "bee_05";
arr["5"] = "bee_5";
arr[06] = "bee_06";
arr["0a"] = "bee_0a";
arr["b"] = "bee_b";
const arr = [];
function setup() {
	console.log(arr);
	arr[0] = "cat";
	arr[1] = "bird";
	arr[2] = "dog";
	arr["3"] = "fish";
	arr["a"] = "lion";
	arr.push("tiger");

	arr["05"] = "bee_05";
	arr["5"] = "bee_5";
	arr[06] = "bee_06";
	arr["1a"] = "bee_1a";
	arr["b"] = "bee_b";

	for (item of arr) {
		console.log(item);
	}
	console.log(arr);
}

結果如下
結果如下

從結果可看出
arr["5"], arr[06] 會視為是 arr[5], arr[6] 算是數字的流水號
arr["05"],arr["0a"],arr["b"] 會視為文字流水號,
陣列長度計算出來為 7

0: "cat"
1: "bird"
1a: "bee_0a"
2: "dog"
3: "fish"
4: "tiger"
05: "bee_05"
5: "bee_5"
6: "bee_06"
a: "lion"
b: "bee_b"

不過,陣列的排序就有點混亂
基本上,數字流水號與文字流水號會分開排序
至於混合在一起時,只要錯開來看順序就好。
比較特別是 arr["05"] 的順序,是排在 arr["5"]之前
而不是在 arr["0"]之後

經測試結果為,主要還是以數字流水號為陣列處理的對象
console.log(arr);
會以數字流水號來排序
數字流水號排序

console.log(arr.sort());
會以陣列元素內容 正向排序
正向排序

console.log(arr.sort());
console.log(arr.reverse());
會以陣列元素內容 反向排序
反向排序

文字流水號並不會做排序上的處理
而且除非是用 console.log(arr); 將陣列元素全部列出
否則以迴圈方式
for (item of arr) {
console.log(item);
}

或是用 arr.map(x => x) 將陣列複製一份,
文字流水號的陣列元素,都不會被看到,也不會被處理,
因此,盡可能不要在陣列中,使用文字流水號。

如果使用了sort排序後,原本以流水號排序的順序就會遺失
新的流水號順序,是以sort排序的流水號排列
因此,流水號的內容,會隨著陣列不同的操作而改變,
而不是像文字流水號的內容是固定的。

因此,若要對文字流水號的內容進行排序的話,
就要用不同的方法了。

將文字流水號改成數字流水號,內容以物件的格式設定

首先,要將 arr["05"] = "bee_05";
改以 arr[5] = { id: "05", value: "bee_05" };

arr[3] = { id: "a", value: "lion" };
arr[5] = { id: "05", value: "bee_05" };
arr[9] = { id: "1a", value: "bee_1a" };
arr[10] = { id: "b", value: "bee_b" };

排序的程式改寫為

arr.sort((a, b) => {
    var nameA = (a.id != undefined)? a.value.toUpperCase() : a; 
    var nameB = (b.id != undefined)? b.value.toUpperCase() : b;
    console.log(nameA + ", " + nameB);

    if (nameA < nameB) {
        return -1;
    }
    if (nameA > nameB) {
        return 1;
    }
    return 0;
});
console.log(arr);

nameA, nameB 為兩兩比較的數值,比較的結果,大於,小於,等於,
分別代表排序的規則,也就是正向排序,或是反向排序,

正向排序
if (nameA < nameB) { return -1; }
if (nameA > nameB) { return 1; }

反向排序
if (nameA < nameB) { return 1; }
if (nameA > nameB) { return -1; }

最後的程式碼為

const arr = [];
function setup() {
	console.log(arr);
	arr[0] = "cat";
	arr[1] = "bird";
	arr[2] = "dog";
	arr[4] = "fish";
	arr[6] = "tiger";
	arr[7] = "bee_5";
	arr[8] = "bee_06";

	arr[3] = { id: "a", value: "lion" };
	arr[5] = { id: "05", value: "bee_05" };
	arr[9] = { id: "1a", value: "bee_1a" };
	arr[10] = { id: "b", value: "bee_b" };
    
	arr.sort((a, b) => {
		var nameA = (a.id != undefined)? a.value.toUpperCase() : a; 
		var nameB = (b.id != undefined)? b.value.toUpperCase() : b;
        console.log(nameA + ", " + nameB);

		if (nameA < nameB) {
			return -1;
		}
		if (nameA > nameB) {
			return 1;
		}
		return 0;
	});

	console.log(arr);
}

以數字流水號來排序
數字流水號來排序

以陣列元素內容 正向排序,分成物件與文字內容分開排序,物件會排在前段
以陣列元素內容 正向排序

以陣列元素內容 反向排序,分成物件與文字內容分開排序,物件會排在後段
以陣列元素內容 反向排序

參考資料
Array.prototype.sort()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

JavaScript Array Reference
https://www.w3schools.com/jsref/jsref_obj_array.asp


上一篇
D18_檔案操作(JSON檔)
下一篇
D20_陣列資料操作[資料逐筆處理,搜尋,篩選,轉換]
系列文
從新開始學習p5.js畫出一片天40
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言