第 3 章 - 陣列與字串

陣列操作

JavaScript 的陣列宣告非常簡單,就是用 [ ... ] 所框起來的一連串資料。以下我們啟動 node之後用交談的方式先進行一些陣列操作的示範,以便讓讀者能實際體會《陣列到底是甚麼?》

陣列存取

$ node
> a=[0,1,2]
[ 0, 1, 2 ]
> a
[ 0, 1, 2 ]
> a[0]
0
> a[1]
1
> a[2]
2
> a[3]
undefined
> a[4]
undefined
> a[9]
undefined
> a[9]=9
9
> a
[ 0, 1, 2, , , , , , , 9 ]
> a[0]=7
7
> a
[ 7, 1, 2, , , , , , , 9 ]
>

函數操作

在 javascript 當中,陣列是一種《物件》,裡面有很多可以呼叫的函數,像是 push, pop, shift, unshift, join, reverse, slice, sort .... 等等,我們可以透過這些函數對陣列進行操作,取得我們所想要的結果。以下是一系列的互動示範。

> a = [1,2,3]
[ 1, 2, 3 ]
> a.push(4) // 把 4 推入陣列尾端
4
> a
[ 1, 2, 3, 4 ]
> a.push(5) // 再把 5 推入
5
> a
[ 1, 2, 3, 4, 5 ]
> a.concat([6,7,8]) // 將兩陣列連接起來後傳回,但必須注意這並不會改變 a 的內容。
[ 1, 2, 3, 4, 5, 6, 7, 8 ]
> a                 // a 的內容並沒有改變
[ 1, 2, 3, 4, 5 ]
> b=a.concat([6,7,8]) // 如果想把連接的結果記住,可以塞給某變數,例如 b 。
[ 1, 2, 3, 4, 5, 6, 7, 8 ]
> b
[ 1, 2, 3, 4, 5, 6, 7, 8 ]
> a
[ 1, 2, 3, 4, 5 ]
> a.join(':') // 把陣列用 : 符號連接成一個字串。
'1:2:3:4:5'
> a.join()    // 把陣列連接成一個字串 (預設連接符號為 ,)
'1,2,3,4,5'
> a.pop       // 陣列.pop 是一個函數
[Function: pop]
> a.pop()     // 呼叫該函數可以《彈出》最後的那個元素!
5
> a           // 《彈出後》該陣列尾端的元素就移除了!
[ 1, 2, 3, 4 ]
> a.reverse() // 將陣列反轉!
[ 4, 3, 2, 1 ]
> a           // reverse 之後陣列就真的反轉了,原本的 a 被修改成反轉後的狀態!
[ 4, 3, 2, 1 ]
> a.shift()   // 從陣列頭部取出一個元素。
4
> a           // shift 之後,頭部的元素就真的移除了!
[ 3, 2, 1 ]
> b           // 上次用 a.concat([6,7,8]) 所做出來的 b 元素還在。
[ 1, 2, 3, 4, 5, 6, 7, 8 ]
> b.slice(2,4) // 用 slice 取出其中第 2 個到第 4 個之間的子陣列。 (注意:這只會傳回 b[2], b[3], 不包含 b[4])
[ 3, 4 ]
> b.slice(2,6) // 取出其中第 2 個到第 6 個之間的子陣列。
[ 3, 4, 5, 6 ]
> a            // 再次看看 a 的內容
[ 3, 2, 1 ]
> a.sort()     // 將 a 排序 (預設為由小到大排列)
[ 1, 2, 3 ]
> a            // a 的內容被從小到大排列了!
[ 1, 2, 3 ]
> b
[ 1, 2, 3, 4, 5, 6, 7, 8 ]
> r=b.splice(1,3, "a", "b", "c", "d") // splice 的功能有點複雜,是將指定的 (1,3) 區間移除後,再插入後面的那些元素。
[ 2, 3, 4 ]
> r                                   // 所以 (1,3) 區間內的 (2,3,4) 被移除了。
[ 2, 3, 4 ]
> b                                   // 然後又塞入了 "a", "b", "c", "d" 這四個元素!
[ 1, 'a', 'b', 'c', 'd', 5, 6, 7, 8 ]
>

當您會使用互動式的方式操作陣列之後,就可以開始撰寫有關陣列的程式了。

一維陣列

JavaScript 的陣列宣告非常簡單,就是用 [...] 所框起來的一連串資料,或者您也可以用 new Array() 語句來建立一個空的陣列,而且可以用 length 屬性來取得陣列大小。

檔案:array.js

var a=[1,6,2,5,3,6,1];

for (i=0;i<a.length;i++) {
  console.log("a[%d]=%d", i, a[i]);
}

執行結果

D:\jsbook>node array.js
a[0]=1
a[1]=6
a[2]=2
a[3]=5
a[4]=3
a[5]=6
a[6]=1

當然、javascript 有些語法是 C 語言所沒有的,像是 JavaScript 的 foreach 語句採用 for (i in c) 這樣的語法,其中的 c 必須是個陣列或容器,而 i 則是索引值 (注意、不是內容,是索引值),以下是這種語句的一個範例。

檔案:foreach.js

var a=[1,6,2,5,3,6,1];

for (i in a) {
  console.log("a[%d]=%d", i, a[i]);
}

執行結果

D:\jsbook>node foreach
a[0]=1
a[1]=6
a[2]=2
a[3]=5
a[4]=3
a[5]=6
a[6]=1

二維陣列

除了一維陣列、我們也可以宣告二維、三維、甚至更高維的陣列,以下是一個將二為陣列格式化為字串後印出來的範例。

檔案:array2D.js

var a=[[1,6,2],
       [5,3,6]];

for (var i=0; i<a.length; i++) {
  var line = "";
  for (var j=0; j<a[i].length; j++) {
    line = line + a[i][j] + " ";
  }
  console.log(line);
}

執行結果

D:\jsbook>node array2D
1 6 2
5 3 6

字串

javascript 語言中的字串,基本上您可以想像為一個《字元陣列》,但必須注意的是,字串和陣列還是有少許不同的,例如字串裏就沒有 push 這個函數,但是卻有 substr 這樣的字串函數。

接著、還是讓我們用交談的方式,先練習一下字串的操作方式!

字串操作

$ node
> x = "hello"
'hello'
> x.length
5
> x[3]
'l'
> x[2]
'l'
> x[1]
'e'
> x[0]
'h'
> x[5]
undefined
> x[4]
'o'
> x=x+" world" // 字串可以用 + 號進行連接 (請注意 + 號對字串和數值有不同的意義,如果您將 "3"+"4" 會得到 "34",而不是 7)。
'hello world'
> x
'hello world'
>

字串函數

javascript 的字串有兩個函數可以用來取出子字串,一個是 substr, 另一個是 substring, 這兩個函數的第二個參數意義不同,其函數規格如下所示:

str.substr(start[, length]) : 第二個參數是長度
str.substring(indexStart[, indexEnd]) : 第二個參數是結尾的位置

字串操作:

> x = "0123456789"
'0123456789'
> x.substr(3,2) // 從第 3 個開始取出長度為 2 的子字串。
'34'
> x.substr(4,5) // 從第 4 個開始取出長度為 5 的子字串。
'45678'
> x.substring(3,7) // 取出從第 3 個開始到第 7 個之前的子字串。(不包含第 7 個)
'3456'
> x.substring(3,9)) // 取出從第 3 個開始到第 9 個之前的子字串。(不包含第 9 個)
'345678'
> x.length  // 取出字串 x 的長度
10
> s = "abCDEfg" // 設定 s 字串
'abCDEfg'
> s.toUpperCase() // 把 s 轉大寫後傳回
'ABCDEFG'
> s.toLowerCase() // 把 s 轉小寫後傳回
'abcdefg'
> y = "     abc      " // y 是一個有前後空白的字串
'     abc      '
> y.trim() // trim() 會把前後的空白去掉
'abc'
> s            // 雖然做了轉大小寫的動作,但是不會改變 s 的值。
'abCDEfg'
> s.concat(y) // 將 s 和 y 進行連接
'abCDEfg     abc      '
> s.charAt(5) // 取出第 5 個字元
'f'
> s.charCodeAt(5) // 取出第 5 個字元的 unicode 代碼
102
> s.charCodeAt(0) // 取出第 0 個字元的 unicode 代碼
97
> s.charAt(0) // 取出第 0 個字元
'a'
> s.slice(3) // 切出第 3 個之後的內容
'DEfg'

結語

雖然陣列和字串都可以用 a[i] 這種方式存取裡面的元素,但是兩者所具有的函數還是不一樣的。

在 javascript 裡面,字串並非一種陣列,因此我們可以對陣列進行 push 等動作,但是卻不能對字串進行 push 動作,否則會發生錯誤的!

以下是一個誤用的範例:

D:\cccwd2\file\jsh\code>node
> "abc".push("d")
TypeError: "abc".push is not a function
    at repl:1:7
    at REPLServer.defaultEval (repl.js:248:27)
    at bound (domain.js:280:14)
    at REPLServer.runBound [as eval] (domain.js:293:12)
    at REPLServer.<anonymous> (repl.js:412:12)
    at emitOne (events.js:82:20)
    at REPLServer.emit (events.js:169:7)
    at REPLServer.Interface._onLine (readline.js:210:10)
    at REPLServer.Interface._line (readline.js:549:8)
    at REPLServer.Interface._ttyWrite (readline.js:826:14)
> ["a", "b", "c"].push("d")
4

所以在使用 javascript 裡面,記得不要把字串誤以為是陣列來用喔!

習題

本章習題絕大部分都需要先學會函數之後才能實作,因此請再看完第4章後再來練習本章習題!

陣列處理習題

  1. 請在一個已經排序的陣列中之正確位置插入一個數值。
    • 範例: insert([1,2,5,6,7], 3) => [1,2,3,5,6,7]
  2. 請用二分搜尋法搜尋一個已經排好序的陣列。
    • 範例: find([ 1, 4, 5, 8, 9], 5) => 2 , 找不到時傳回 -1。
  3. 請將 a 到 b 之間無法被 3, 5, 7 整除的數字放到陣列中?
    • 範例: filter357(5,10) = [8]
    • 範例: filter357(5,15) = [8,11,13]
  4. 請算出某陣列的平均值?
    • 範例: mean([1,2,3,4,5]) => 3
  5. 請算出某陣列的樣本標準差? (標準差為 (xi-x)^2/(n-1) 的總和)
    • 範例: sd([1,2,3,4,5]) = sqrt((2^2+1^2+0^2+1^2+2^2)/4) = sqrt(2.5)=1.58。
  6. 請寫一個函數找出一個排序好陣列中差異最小的兩個數之差距?
    • 範例: minGap([1,3,6,7,10]) = 1
  7. 請寫一個函數 random(n, a, b) 可以產生 n 個介於 a 到 b 之間的浮點亂數?
    • 範例: random(3, 10, 20)= [13.76, 19,23, 14,11]
  8. 寫一個程式做因數分解。
    • 範例:factor(45) => [3, 3, 5]

矩陣處理習題

  1. 寫一個程式把矩陣轉置。
    • 範例:transpose([[1,2,3], [3,2,1]]) => [[1,3], [2,2], [3,1]]
  2. 請寫一個函數計算兩矩陣相加?
    • 範例: add([[1,2],[3,4]], [[1,1],[1,1]]) => [[2,3], [4,5]]
  3. 請寫一個函數計算兩矩陣相減?
    • 範例: sub([[1,2],[3,4]], [[1,1],[1,1]]) => [[0,1], [2,3]]
  4. 請寫一個函數計算兩矩陣相乘?
    • 範例: mul([[1,2],[3,4]], [[1,1],[1,1]]) => [[3,3], [7,7]]
  5. 請寫一個函數 neg(A) 傳回某矩陣 A 的負矩陣 -A。
    • 範例: neg([[1,2],[3,4]]) => [[-1,-2],[-3,-4]]
  6. 請寫一個函數判斷某方陣是否每行每列的加總都是一樣的?
    • 範例: isMagic([[1,2,3], [2,3,1], [3,1,2]]) = true
    • 範例: isMagic([[1,2,3], [2,3,1], [3,2,1]]) = false
  7. 請寫一個函數可以把 n*m 個數值的陣列改變為的矩陣?
    • 範例: asMatrix([1,2,3,4,5,6], 2, 3) => [[1,2,3],[4,5,6]]

字串處理習題

  1. 請判斷一個字串是否是一個迴文?
    • 範例: palindrome("abcba") => true
  2. 請將輸入的字串翻轉?
    • 範例 reverse("abcde") => "edcba"
  3. 請輸出某二進位字串的偶校驗位元 (parity bit)
    • 範例: evenParity("1010001") => 1
  4. 請輸出某二進位字串的1補數
    • 範例: complement1("10101010") => "01010101"
  5. 請寫一個程式檢查數學是中的括號是否合法?
    • 範例: isPaired("(a+3)*5/7)))*8") => false

results matching ""

    No results matching ""