Ruby Array

Ruby 教學 7 – Ruby Array Object 介紹

Ruby Array object 也是個很常用到的 object,再加上有許多 methods 可以對 Array object 做操作,個人認為算是最重要的一個 object。

1. 宣告 Ruby Array Object

1.1 Array.new

跟其他大部分的 object 一樣,Array object 可以直接用 class.new 創造一個新的 object instance,可以給兩個 arguments:

  • 第 1 個 argument 是 Array object 的長度
  • 第 2 個 argument 是 Array object 所有 element 的 default value
p Array.new
# []
p Array.new(3)
# [nil, nil, nil]
p Array.new(3, 10)
# [10, 10, 10]

1.2 Array (Kernel Module)

Array object 也可以直接用 Array 這個 key word 來創造新的 Array object instance,不過這個 Array 是由 Kernel module 提供,和原本的 Array class 不一樣。

p Array(["a", "b"])
# ["a", "b"]
p Array(1..5)
# [1, 2, 3, 4, 5]
p Array(key: :value)
# [[:key, :value]]
p Array(nil)
# []
p Array(1)
# [1]

2. Operstors

在 Array object 中也可以使用 operators 來對陣列做操作,要注意的是,在 Array object 中,所有 operators 都不會改變原本的 Array object!

2.1 +

會直接將 + 後面的 Array object 的所有元素加到 + 前面的 Array object:

arr1 = [1, 2, 3, 4]
arr2 = [5, 6]

p arr1 + arr2
# [1, 2, 3, 4, 5, 6]
p arr1
# [1, 2, 3, 4]

2.2 –

在 – 前面的 Array object 中,如果有 – 後面 Array object 中的任一元素,會被刪除:

arr1 = [1, 1, 2, 2, 3, 3, 3, 3, 4, 5]
arr2 = [2, 3]

p arr1 - arr2
# [1, 1, 4, 5]
p arr1
# [1, 1, 2, 2, 3, 3, 3, 3, 4, 5]

2.3 *

會將 * 前面的 Array object 重複 * 後面的次數後,放回 Array object:

arr = [1, 3, 5]

p arr * 3
# [1, 3, 5, 1, 3, 5, 1, 3, 5]
p arr
# [1, 3, 5]

2.4 | (Union Sign)

Union 的中文是聯集,會比較 | 左右兩邊的 Array object,將兩邊都出現過的元素都取出並刪除重複項:

arr1 = [1, 1, 2, 3, 3]
arr2 = [3, 4, 4, 5]

p arr1 | arr2
# same as p arr1.|(arr2)
# [1, 2, 3, 4, 5]

arr3 = [4, 5, 6, 7]

p arr1 | arr2 | arr3
# [1, 2, 3, 4, 5, 6, 7]
p arr1
# [1, 1, 2, 3, 3]

2.5 & (Ampersand Sign)

& 是交集,只取出兩邊都出現過的元素:

arr1 = [1, 1, 2, 3, 3]
arr2 = [3, 4, 4, 5]

p arr1 & arr2
# [3]
p arr1
# [1, 1, 2, 3, 3]

2.6 Equal ==

在 Ruby 中, == 只會比較兩邊的 value,即便兩邊的 Array object 記憶體位置不同,只要 value 相同,就會回傳 true:

在 Ruby 中,=== 是 == 的 Alias (別名),兩者的功能一模一樣
arr1 = [1, 2, 3]
arr2 = [1, 2, 3]

# object_id 可以用來取得 object 的記憶體位置
p arr1.object_id
# 60
p arr2.object_id
# 80
p arr1 == arr2
# true
p arr1 === arr2
# true

# 可以用以下方法從記憶體位置取得 value
p ObjectSpace._id2ref(arr1.object_id)
# [1, 2, 3]

2.7 Inequal !=

和 == 相反:

arr1 = [1, 2, 3]
arr2 = [3, 2, 1]

p arr1 != arr2
# true

2.8 <=>

會從兩邊的第一個元素開始比較,不相等就往下一個 index 繼續比較,兩邊都相等就回傳 0:

p [1, 2, 3] <=> [1, 2, 3]
# 0
p [1, 2, 3] <=> [1, 2, 4]
# -1
p [4, 2, 3] <=> [1, 2, 3]
# 1
p [4, 2, 3] <=> [1, 2, 3, 4]
# 1
p [1, 2, 3] <=> [1, 2, 3, 4]
# -1

3. Array Instance Methods I – 屬性

3.1 Array length/size

.length 用來取得 Array object 的長度,和 .size 一樣:

teams = ["Jimmy", "Eric", "Sam"]

p teams.length
# 3
p teams.size
# 3

3.2 Access Array Item

可以用 [] 來取得第幾個 Array object 的元素:

  • [0] 代表第一個元素
  • [-1] 代表最後一個元素
  • 如果超過 Array object 的長度,會回傳 nil
teams = ["Jimmy", "Eric", "Sam"]

p teams[2]
p teams.[](2)
# "Sam"

p teams[-2]
p teams.[](-2)
# "Eric"

p teams[100]
# nil

3.3 Array fetch

.fetch 和用 [] 存取元素類似,差別在於超過 Array object 時,如果沒有給第二個 argument 會有 Error,有給第二個 argument 的話,會回傳第二個 argument:

teams = ["Jimmy", "Eric", "Sam"]

p teams[2]
p teams.fetch(2)
# "Sam"

p teams[-2]
p teams.fetch(-2)
# "Eric"

p teams.fetch(100)
# Error!
p teams.fetch(100, "Unknown")
# "Unknown"

3.4 Array first last

.first 和 .last 分別可以存取前幾個和最後幾個 Array object 的元素:

  • 沒有 argument 時,會分別回傳第一個和最後一個元素
  • 有 argument n 時,會以 Array object 的形式,回傳前 n 個和最後 n 個元素
arr = [1, 3, 5, 7, 9]

p arr.first
# 1
p arr.first(1)
# [1]
p arr.first(3)
# [1, 3, 5]

p arr.last
# 9
p arr.last(1)
# [9]
p arr.last(3)
# [5, 7, 9]

3.5 Array values_at

values_at 會以 Array object 的形式回傳指定 index 的元素:

arr = [1, 3, 5, 7, 9]

p arr.values_at(1, 3, 4)
# 取出 index = 1, 3, 4 的 items
# [3, 7, 9]

3.6 Array index/find_index

.index 和 .find_index 的功能相同,都是找到陣列中的某元素 index 並回傳:

arr = [1, 3, 5, 7, 3]

p arr.index(3)
# 1
p arr.find_index(3)
# 1
p arr.index(10)
# nil

3.7 Array max min

.max 和 .min 會回傳 Array object 中最大和最小的元素:

arr1 = [1, 3, 5, 7, 9]
arr2 = ["Jimmy", "Eric", "Sam"]

p arr1.max
# 9
p arr1.min
# 1
p arr2.max
# "Sam"
p arr2.min
# "Eric"

3.8 Array include?

.include? 用來判斷這個 Array object 是否包含某元素:

arr = [1, 3, 5, 7, 3]

p arr.include?(3)
# true
p arr.include?(10)
# false

3.9 Array count

.count 會計算這個元素出現過幾次並回傳,如果沒有 argument 時,會回傳 Array object 的 length:

arr = [1, 3, 5, 7, 9, 3]

p arr.count
# 6
p arr.count(10)
# 0
p arr.count(3)
# 2

3.10 Array sample

.sample 用來取得隨機個 Array item,有給 argument 時會回傳 Array object:

names = ["Jimmy", "Jacky", "Sam", "Sandy", "Susan", "Eric"]

# 會發現每次執行時,印出的結果都不完全相同
p names.sample
# "Sam"
p names.sample(1)
# ["Sam"]
p names.sample(3)
# ["Sandy", "Sam", "Susan"]

3.11 Array empty?

用來判斷是不是空陣列:

arr1 = [1, 3, 5, 7, 9]
arr2 = []

p arr1.empty?
# false
p arr2.empty?
# true

4. Array Instance Methods II – 操作 (不改變原 Object)

4.1 Array slice

.slice 和直接在 [] 放 Range object 的功能一樣,都是截取陣列的某段元素:

arr = [1, 3, 5, 7, 9, 11, 13]

# index == 2 的元素
p arr.slice(2)
p arr[2]
# 5

# 從 index == 2 截取 4 個元素
p arr.slice(2, 4)
p arr[2, 4]
# [5, 7, 9, 11]

# 從 index == 2 截取到 index == 4 (包含 index == 4)
p arr.slice(2..4)
p arr[2..4]
# [5, 7, 9]

# 從 index == 2 截取到 index == 4 (不包含 index == 4)
p arr.slice(2...4)
p arr[2...4]
# [5, 7]

4.2 Array reverse

.reverse 會將 Array object 順序顛倒後回傳:

arr = [1, 3, 5, 7, 9, 11, 13]

p arr.reverse
# [13, 11, 9, 7, 5, 3, 1]

4.3 Array uniq

.uniq 會刪除陣列重複項,也可以加上 block,指定要刪除的條件:

arr = [0, 0, 1, 1, 2, 2]

p arr.uniq
# [0, 1, 2]

arr = ["a", "aa", "aaa", "b", "bb", "bbb"]

p arr.uniq { |element| element.size }
# ["a", "aa", "aaa"]

4.4 Array compact

.compact 會移除陣列中的 nil 元素:

arr = [nil, 0, nil, 1, nil, 2, nil]

p arr.compact
# [0, 1, 2]

4.5 Array flatten

.flatten 會把多維陣列攤平:

arr = [ 0, [ 1, [2, 3], 4 ], 5 ]

p arr.flatten
# [0, 1, 2, 3, 4, 5]

p arr.flatten(0)
# [0, [1, [2, 3], 4], 5]
p arr.flatten(1)
# [0, 1, [2, 3], 4, 5]
p arr.flatten(2)
# [0, 1, 2, 3, 4, 5]
p arr.flatten(3)
# [0, 1, 2, 3, 4, 5]

4.6 Array zip

a = [:a0, :a1, :a2, :a3]
b = [:b0, :b1, :b2, :b3]
c = [:c0, :c1, :c2, :c3]

p a.zip(b, c)
# [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]


a = [:a0, :a1, :a2, :a3]
b = [:b0, :b1, :b2]
c = [:c0, :c1]

p a.zip(b, c)
# [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, nil], [:a3, nil, nil]]


a = [:a0, :a1, :a2, :a3]
b = [:b0, :b1, :b2, :b3, :b4]
c = [:c0, :c1, :c2, :c3, :c4, :c5]

p a.zip(b, c)
# [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]

4.7 Array dup

.dup 會複製一個 Array object:

arr1 = [1, 2, 3]
arr2 = arr1.dup

p arr2
# [1, 2, 3]
p arr1.object_id
# 60
p arr2.object_id
# 80

5. Array Instance Methods III – 操作 (會改變原 Object)

5.1 <<

會將元素加到 Array object 的末端:

arr1 = [1, 2, 3]
arr1 << 4 << 5

p arr1
# [1, 2, 3, 4, 5]

5.2 Array push/append

一樣會將元素加到 Array object 的末端,和 append 的功能一樣:

arr1 = [1, 2, 3]

arr1.push(4)
p arr1
# [1, 2, 3, 4]

arr1.push(5, 6)
p arr1
# [1, 2, 3, 4, 5, 6]

5.3 Array pop

.pop 沒給 argument 時會將 Array object 的末端元素刪除並回傳,有給 argument 實則決定要刪除幾個元素,並以 Array object 的形式回傳:

arr1 = [1, 2, 3, 4, 5]
p arr1.pop
# 5
p arr1
# [1, 2, 3, 4]

p arr1.pop(2)
# [3, 4]
p arr1
# [1, 2]

5.4 Array unshift

.unshift 會將元素加到 Array object 最前端:

arr1 = [1, 2, 3]

arr1.unshift(4)
p arr1
# [4, 1, 2, 3]

arr1.unshift(5, 6)
p arr1
# [5, 6, 4, 1, 2, 3]

5.5 Array shift

.shift 沒給 argument 時會將 Array object 的首端元素刪除並回傳,有給 argument 實則決定要刪除幾個元素,並以 Array object 的形式回傳:

arr1 = [1, 2, 3, 4, 5]
p arr1.shift
# 1
p arr1
# [2, 3, 4, 5]

p arr1.shift(2)
# [2, 3]
p arr1
# [4, 5]

5.6 Array fill

.fill 會將 Array object 以某個 value 填滿:

arr1 = [1, 2, 3, 4, 5]
arr1.fill(0)

p arr1
# [0, 0, 0, 0, 0]

5.6 Array concat

.concat 可以結合多個 Array object:

arr1 = [1, 2, 3, 4, 5]
arr2 = [3, 5, 7]

arr1.concat(arr2)
p arr1
# [1, 2, 3, 4, 5, 3, 5, 7]

arr3 = [2, 4]
arr4 = [6, 8]

arr1.concat(arr3, arr4)
p arr1
# [1, 2, 3, 4, 5, 3, 5, 7, 2, 4, 6, 8]

5.7 Array insert

.insert 可以將元素插入 Array object 的某個 index 中:

arr1 = [1, 2, 3, 4, 5]

arr1.insert(1, 10)
p arr1
# [1, 10, 2, 3, 4, 5]

arr1.insert(2, "Jimmy", "Sam")
p arr1
# [1, 10, "Jimmy", "Sam", 2, 3, 4, 5]

5.8 Overwrite Arrat Items

可以直接賦值給某一段 Array object:

numbers = [1, 3, 5, 7, 15, 21]

numbers[3, 2] = 0
p numbers
# [1, 3, 5, 0, 21]

numbers[0..2] = [7, 9, 11]
p numbers
# [7, 9, 11, 0, 21]

6. Array Instance Methods IV – 包含 block

6.1 Array each

.each 可以遍歷所有 Array object 元素,相當於 JavaScript 的 forEach:

numbers = [1, 3, 5]

numbers.each do |element|
  p element
end
# 1
# 3
# 5

6.2 Array each_with_index

.each_with_index 在 block 中加了另一個變數,讓你可以取得目前是在 Array object 的哪個 index:

numbers = [1, 3, 5]

numbers.each_with_index do |element, index|
  p "value #{element} is index #{index}"
end
# "value 1 is index 0"
# "value 3 is index 1"
# "value 5 is index 2"

6.3 Array map/collect

.map 會針對 Array object 的每個元素做某些操作後再回傳:

# ex1
numbers = [1, 3, 5]

numbers = numbers.map do |element|
  element * 2
end

p numbers
# [2, 6, 10]

# ex2
numbers = [1, 3, 5]

numbers = numbers.map do |element|
  element.to_s
end

# 可以簡寫成:
numbers = numbers.map(&:to_s)

p numbers
# ["1", "3", "5"]

6.4 Array select

.select 會將 Array object 以某個條件過濾掉某些元素,相當於 JavaScript 中的 .filter:

numbers = [1, 2, 3, 4, 5, 6]

numbers = numbers.select { |element| element.odd? }
p numbers
# [1, 3, 5]

6.5 Array reject

.reject 和 .select 相反,.select 只會保留回傳 true 的 element,.reject 則只會保留回傳 false 的 element:

numbers = [1, 2, 3, 4, 5, 6]

numbers = numbers.reject { |element| element.odd? }
p numbers
# [2, 4, 6]

6.6 Array partition

.partition 則是結合 .select 和 .reject,會將回傳 true 的 element 以 Array object 的形式放在第一個元素,將回傳 false 的 element 以 Array object 的形式放在第二個元素:

numbers = [1, 2, 3, 4, 5, 6]

odds = numbers.select { |element| element.odd? }
evens = numbers.reject { |element| element.odd? }
p odds
# [1, 3, 5]
p evens
# [2, 4, 6]

p numbers.partition { |element| element.odd? }
# [[1, 3, 5], [2, 4, 6]]

6.7 Array sort

.sort 會排序 Array object,沒有 block 時會直接由小排到大,有給 block 時,則可以決定排順序的規則:

numbers = [1, 6, 5, 3, 7, 9, 2]

p numbers.sort
# [1, 2, 3, 5, 6, 7, 9]
p numbers.sort { |a, b| b <=> a }
# [9, 7, 6, 5, 3, 2, 1]

6.8 Array any?

用來判斷 Array object 中是否有符合某條件的 element,只要有一個,就會回傳 true:

arr1 = [1, 3, 5, 2]
arr2 = [2, 4, 6]

p arr1.any? { |v| v.even? }
# true
p arr2.any? { |v| v.odd? }
# false

6.9 Array all?

用來判斷 Array object 中是否所有 element 都符合某條件,只要有一個 element 不符合,就會回傳 false:

arr1 = [1, 3, 5, 2]
arr2 = [2, 4, 6]

p arr1.all? { |v| v.odd? }
# false
p arr2.all? { |v| v.even? }
# true

6.10 Array find

找到 Array object 中符合某條件的 element:

arr1 = [1, 3, 5, 9, 12, 15]

p arr1.find { |v| v % 3 == 0 && v % 5 == 0 }
# 15

6.11 Array reduce

和 JavaScript 的 reduce 相同:

result = [10, 20, 30, 40].reduce(0) do |previous, current|
  puts "The previous value is #{previous}"
  puts "The current value is #{current}"
  previous + current
end

p result
The previous value is 0
The current value is 10
The previous value is 10
The current value is 20
The previous value is 30
The current value is 30
The previous value is 60
The current value is 40
100

7. Array Instance Methods V – 轉換成其它 Object

7.1 Array join

將 Array object 以某特字元連結,並轉換成 String object:

teams = ["Jimmy", "Sam", "Eric"]

p teams.join
# "JimmySamEric"
p teams.join(", ")
# "Jimmy, Sam, Eric"
p teams.join("-")
# "Jimmy-Sam-Eric"

7.2 Array to_s

直接將 Array object 轉換成 String object:

arr = [1, 3, 5]

p arr.to_s
# "[1, 3, 5]"

7.3 Array to_h

將 Array object 轉換成 Hash object:

arr = ['foo', :bar, 1, [2, 3], {baz: 4}]

p arr.to_h { |item| [item, item] }
# {"foo"=>"foo", :bar=>:bar, 1=>1, [2, 3]=>[2, 3], {:baz=>4}=>{:baz=>4}}

p [].to_h
# {}

arr = [["Jimmy", 25], ["Sam", 24], ["Eric", 23]]
p arr.to_h
# {"Jimmy"=>25, "Sam"=>24, "Eric"=>23}

8. 參考資料

Learn to Code with Ruby
Class: Array (Ruby 3.1.2)

如果覺得我的文章有幫助的話,歡迎幫我的粉專按讚哦~謝謝你!

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top