配列を扱うためにはArrayクラスを使います。

プログラムで配列を定義する

プログラム中で配列を定義するには以下のように記述します。

 fruits = ["apple", "orange", "lemon"]
 scores = [55, 49, 100, 150, 0]

配列を参照する場合はArray#[]メソッドを使い、引数として配列の要素番号を指定します。要素番号は0から始まります。

上の例ではfruits[0]は”apple”、scores[3]は150を返します。

以下のように配列をネスト(入れ子)にすることもできます。

 fruits = [3, ["apple", 250], ["orange", 400], ["lemon", 300]]
 
 p fruits[0] #=> 3
 p fruits[1][1] #=> 250
 p fruits[3][0] #=> "lemon"

文字列リテラルを要素とする配列を % 記法を使って生成する。

 ar = %w(apple banana lemon) #=> ["apple", "banana", "lemon"] 
'('  ')' 以外に [], {},  || などが使えます。

要素となる文字列に空白を含めたいときには,バックスラッシュを使えます。

 ar = %w( red\ apple sweet\ banana )

m x n 行列の形で配列の配列を初期化する

次の形で初期化すると,4個の配列は同じオブジェクトなので全部変わってしまいます.

リファレンスマニュアルには [[trap:Array]]となっているところです.

 dary = Array.new(4,Array.new(3,0)) #=> [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
 dary[0][1] = 7 #=> [[0, 7, 0], [0, 7, 0], [0, 7, 0], [0, 7, 0]]

new による初期化に次のようにブロックを使うと,やりたいことができるでしょう.

 dary = Array.new(4){Array.new(3){0}}
 dary[0][1] = 7
 #=>  [[0, 7, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

配列要素をカンマ区切りで出力する

Array#joinメソッドを使うと配列の要素を任意の文字列で区切った文字列を取得することができます。

 p ["apple", "orange", "lemon"].join(',') #=> "apple,orange,lemon"
 p ["apple", "orange", "lemon"].join('#') #=> "apple#orange#lemon"
 p [55, 49, 100, 100, 0].join(',') #=> "55,49,100,100,0"
 p [3, ["apple", 250], ["orange", 400]].join(',') #=> "3,apple,250,orange,400"

配列の要素数を取得する

Array#sizeメソッド、またはArray#lengthメソッドで配列の要素数を取得することができます。

 p ["apple", "orange", "lemon"].size #=> 3
 p ["apple", "orange", "lemon"].length #=> 3
 p [55, 49, 100, 100, 0].size #=> 5
 p [3, ["apple", 250], ["orange", 400]].size #=> 3

配列に要素を追加する

配列を生成した後で要素を追加する場合は、Array#«メソッド、Array#unshiftメソッド、Array#pushメソッドを使用します。

Array#«メソッドは配列の最後に、Array#unshiftメソッドは配列の最初に要素を追加することができます。

 a = [1,2,3,4,5] #=> [1,2,3,4,5]
 
 a << 99 #=> [1,2,3,4,5,99]
 a.unshift(99) #=> [99,1,2,3,4,5,99]

Array#pushメソッドは配列の最後へ要素を追加することができます

 a = [1,2,3,4,5]
 
 a.push(10) #=> [1, 2, 3, 4, 5, 10]

配列の先頭または末尾から要素を取りだす

Array#shiftメソッドでは、配列の先頭から要素を取り出すことができます。 Array#popメソッドは配列の最後から要素を取り出すことができます。Array#shiftメソッド、Array#popメソッドで値を取りだすと、取りだされた要素は配列中から取り除かれます。

 a = [1,2,3,4,5]
 
 a.push(10) #=> [1, 2, 3, 4, 5, 10]
 p a.pop #=> 10
 p a.pop #=> 5
 p a #=> [1, 2, 3, 4]

部分配列を取りだす

Array#[]メソッドまたはArray#sliceメソッドにより配列の一部分を取りだすことができます。

 a = [1,2,3,4,5]
 
 p a[0,2] #=> [1, 2]
 p a[1..3] #=> [2, 3, 4]
 p a.slice(0,2) #=> [1, 2]
 p a.slice(1..3) #=> [2, 3, 4]

Array#sliceメソッドは破壊的メソッドArray#slice!が用意されています。Array#slice!メソッドは指定された部分配列を取り除き、それを返却します。

 a = [1,2,3,4,5]
 
 p a.slice!(0,2) #=> [1,2]
 p a #=> [3,4,5]
 
 p a.slice!(1,2) #=> [4,5]
 p a #=> [3]

配列を任意の値で埋める

Array#fillメソッドにより配列の範囲を任意の値で埋めることができます。Array#fillメソッドは破壊的メソッドです。

 a = [1,2,3,4,5]
 
 a.fill(255, 2,2) #=> [1, 2, 255, 255, 5]
 a.fill(0, 1..2) #=> [1, 0, 0, 255, 5]

配列を空にする

Array#clearメソッドにより配列の要素を空にすることができます。Array#clearメソッドは破壊的メソッドです。

 a = [1,2,3,4,5]
 a.clear #=> []
 
 p a #=> []

配列同士を結合する

+メソッド、Array#concatメソッドにより配列同士を結合することができます。Array#+メソッドはレシーバと指定した配列を結合した結果を返却し、Array#concatメソッドはレシーバ自身へ指定した配列を結合します。

 a = [1,2,3,4,5]
 
 p a + [10, 20] #=> [1, 2, 3, 4, 5, 10, 20]
 p a #=> [1, 2, 3, 4, 5]
 a.concat([10, 20]) #=> [1, 2, 3, 4, 5, 10, 20]
 p a #=> [1, 2, 3, 4, 5, 10, 20]

配列同士の和・積を取る

Array# メソッド、Array#&メソッドで配列同士の和または積をとることができます。Array# メソッドはいずれかの配列に含まれる要素を配列で返却します。この時、両方に含まれる要素は一つにまとめられます。Array#&メソッドは両方に含まれる要素だけを配列で返却します。
 p [1,3,5,7] | [2,4,6,8] #=> [1, 3, 5, 7, 2, 4, 6, 8]
 p [1,2,3,4] | [3,4,5,6] #=> [1, 2, 3, 4, 5, 6]
 
 p [1,3,5,7] & [2,4,6,8] #=> []
 p [1,2,3,4] & [3,4,5,6] #=> [3, 4]

複数の要素を変更する

Array#[]メソッドにより配列中の複数要素を同時に変更することができます。

 a = [1,2,3,4,5]
 
 a[0...2] = [111, 222, 333]
 p a #=> [111, 222, 333, 3, 4, 5]
 
 a[3,2] = [444,555] #=> [444, 555]
 p a #=> [111, 222, 333, 444, 555, 5]

配列の配列をフラットな配列にする

Array#flattenメソッドにより配列を平滑化しフラットな配列にすることができます。Array#flattenメソッドは破壊的メソッドArray#flatten!が用意されています。

 a = [1,[2,[3,4],5],[6,7]]
 
 p a.flatten #=> [1, 2, 3, 4, 5, 6, 7]
 a.flatten! #=> [1, 2, 3, 4, 5, 6, 7]

配列をソートする

Array#sortメソッドにより配列の要素をソート(並び替え)することができます。Array#sortには破壊的メソッドArray#sort!が用意されています。

 p [5,1,4,2,3].sort #=> [1, 2, 3, 4, 5]
 
 a = [5,1,4,2,3]
 a.sort! #=> [1, 2, 3, 4, 5]
 p a #=> [1, 2, 3, 4, 5]
 
 p ["Orange", "Apple", "Lemon"].sort #=> ["Apple", "Lemon", "Orange"]

条件式を指定したソート

Array#sortメソッドではArray#sort{ a,b …}のようにブロックで比較条件を指定することができます。

ブロックではaとbを比較し、等しい場合は0、a<bの場合は負の値、a>bの場合は正の値を返却する必要があります。

 a = ["Hitoshi,045", "Sizuo,046", "Yoshi,0138"]
 
 p a.sort{|a, b| a.split(',')[1] <=> b.split(',')[1]} #=> ["Yoshi,0138", "Hitoshi,045", "Sizuo,046"]

配列の配列を任意の要素でソートする

配列の要素となっている配列の特定の要素をソートキーとしたいことがよくあります.表計算アプリの B, C, … でソートしたいケースみたいなものです. やっていることは上と同様です.

 ar = [[2,"b"],[3,"a"],[1,"c"]]

 ar.sort{|p,q|p[0]<=>q[0]}
 #=> [[1, "c"], [2, "b"], [3, "a"]]

 ar.sort{|p,q|p[1]<=>q[1]}
 # => [[3, "a"], [2, "b"], [1, "c"]]

配列を逆順にする

Array#reverseメソッドにより、配列要素を逆から並び替えることができます。Array#reverseメソッドには破壊的メソッドArray#reverse!も用意されています。

 a = [5,1,4,2,3]
 
 a.sort! #=> [1, 2, 3, 4, 5]
 p a.reverse #=> [5, 4, 3, 2, 1]
 a.reverse! #=> [5, 4, 3, 2, 1]

指定した位置の要素を取り除く

Array#delete_atメソッドにより配列中の指定した位置の要素を取り除くことができます。Array#delete_atはレシーバ自身の値を更新します。

 a = [5,1,4,2,3]
 
 a.delete_at(0) #=> 5
 p a #=> [1, 4, 2, 3]
 
 a.delete_at(1) #=> 4
 p a #=> [1, 2, 3]

一致する要素を全て取り除く

Array#deleteメソッドにより指定した要素と等しいものを全て配列から取り除くことができます。Array#deleteはレシーバ自身の値を更新します。 Array#deleteメソッドへブロックを与えた場合、削除する要素が無かった場合ブロックが実行されます。

 a = ["apple", "orange", "lemon", "apple", "vine"]
 
 a.delete("apple") #=> ["apple"]
 p a #=> ["orange", "lemon", "vine"]
 a.delete("apple") { |x| puts "#{x} not found" } #=> "apple not found"

配列から重複した要素を取り除く

Array#uniqメソッドにより重複した要素を配列から取り除くことができます。Array#uniqメソッドには破壊的メソッドArray#uniq!が用意されています。

 a = [30,20,50,30,10,10,40,50]
 p a.uniq #=> [30, 20, 50, 10, 40]
 
 a = ["/tmp","/home/","/etc","/tmp"]
 a.uniq! #=> ["/tmp", "/home", "/etc"]

配列から指定条件を満たす要素を取り除く

Array#delete_ifメソッド、Array#reject!メソッドはブロックの実行結果が真である要素を取りぞきます。

Array#reject!メソッドには非破壊的メソッドであるArray#rejectがあります。Array#rejectはレシーバの内容は変更せず、与えたブロックの実行結果が真になった要素を取り除いた配列を返します。

 a = [30,100,50,80,79,40,95]
 
 a.delete_if {|x| x < 80} #=> [100, 80, 95]
 p a #=> [100, 80, 95]
 
 p a.reject {|x| x < 90} #=> [100, 95]
 p a #=> [100, 80, 95]
 
 a.reject! {|x| x < 90} #=> [100, 95]
 p a #=> [100, 95]
 
 a = ["Takeuchi", "Tanaka", "Satou", "Andou", "Kurasaki"]
 
 a.delete_if {|x| /^T.*/ =~ x} #=> ["Satou", "Andou", "Kurasaki"]

配列から指定条件を満たす要素を抽出する

Array#select はブロック構文で与えた条件式に一致する要素のみを抽出した配列を返却します。

 a = [1, 2, 3, 4]
 p a.select{|x| x % 2 == 0} # => [2, 4]
 
 b = [['Taro', 'M'], ['Hanako', 'F'], ['Jiro', 'M'], ['Sachiko', 'F']]
 p b.select{|x| x[1]=='M'} # => [["Taro", "M"], ["Jiro", "M"]]

配列中の要素を探す

Array#indexメソッドにより配列から要素を検索することができます。指定された要素が見つかればその位置を、見つからなければnilが返却されます。

 a = ["apple",10,"orange",["lemon","vine"]]
 
 p a.index("apple") #=> 0
 p a.index(10) #=> 1
 p a.index(["lemon","vine"]) #=> 3
 p a.index("fruit") #=> nil

配列の配列を検索する

Array#assocメソッドは配列の配列を検索し、第1要素が等しい最初の配列を返却します。

 a = [["apple",100],["vine",500],["orange",300]]
 
 p a.assoc("apple")  #=> ["apple", 100]
 p a.assoc("orange") #=> ["orange", 300]
 p a.assoc("pear")   #=> nil

配列の各要素にブロックを実行し配列を作成する

collectメソッド、mapメソッドは配列の各要素に対してブロックを実行し、結果を配列で返却します。それぞれ、破壊的メソッドcollect!map!が用意されています。

 a = [10, 20, 30, 40, 50]
 p a.collect {|x| x*10} #=> [100, 200, 300, 400, 500]
 p a #=> [10, 20, 30, 40, 50]
 
 p a.map {|x| x*10} #=> [100, 200, 300, 400, 500]
 p a #=> [10, 20, 30, 40, 50]
 
 a.collect! {|x| x/10} #=> [1, 2, 3, 4, 5]
 p a #=> [1, 2, 3, 4, 5]
 
 a = [["vine", 2, 500], ["orange", 3, 100], ["apple", 10, 50]]
 p a.map {|x| [x[0], x[1]*x[2]]} #=> [["vine", 1000], ["orange", 300], ["apple", 500]]

配列の各要素に対して繰り返しブロックを実行する

Array#eachメソッドにより配列の各要素に対して繰り返しブロックを実行することができます。

 ["Taro", "Hanako", "Ichiro"].each {|x| puts "Hello, #{x}"}
 #=> "Hello, Taro"
 #=> "Hello, Hanako"
 #=> "Hello, Ichiro"

配列の要素の和を求める(each を使う)

 sum = 0
 [1,2,3,4,5,6,7,8,9,10].each {|x| sum += x}
 p sum #=> 55

配列の要素を逆順に繰り返すArray#reverse_eachメソッドも用意されています。

配列の要素の和を求める(inject を使う)

p [1,2,3,4,5,6,7,8,9,10].inject(0) {|sum,x| sum+x}  #=> 55

配列の要素をランダムに抽出する

Ruby 1.8.x

choice を使います。

実行するたびに取り出される要素が異なります。

 [1, 2, 3].choice #=> 3
 [1, 2, 3].choice #=> 1

Ruby 1.9.x / 2.0.x

sample を使います(抽出するという意味です)。

 ["ぐう","ちょき","ぱあ"].sample #=> どれかが抽出されます.

sampleの引数として 1 以上の整数 n を与えると,n 個の要素が無作為抽出され,配列として返されます.

 ["ぐう","ちょき","ぱあ"].sample(2) #=> ["ちょき","ぐう"]などのように抽出されます.

複数の配列を同時に動かす(Ruby 1.9.x 以降)

3つの配列が次のように定義されているとします。

 fruits = %w( mango apple orange)
 prices = [200, 120, 100]
 counts = [5, 10, 12]

これらを同時に回すには,次のようにすると,どれも同等な扱いに書けてきれいです。

 x = fruits.each
 y = prices.each
 z = counts.each
 loop do 
   xx = x.next
   yy = y.next
   zz = z.next
   puts "#{xx} #{yy} #{zz} #{yy * zz}"
 end

二次元,三次元の座標の配列の成分ごとの最大,最小を求める.

Matrixクラスの転置メソッドを使うと,イテレータで配列を回すことなく処理することができます.

 require "matrix"
 points = [[1,5],[8,4],[2,9],[4,3]]
 px = Matrix[*points].t.row(0)  # =>  Vector[1, 8, 2, 4]
 py = Matrix[*points].t.row(1)  #=> Vector[5, 4, 9, 3]
 p_max = px.max #=> 8
 あとも同様です.

Matrixクラスを使わずに Array クラスのmax_by メソッドを使う方法もあります. 大量のデータについては上記の方が速度的に優るかも知れません.

 x_max = points.max_by{|v| v[0] }[0];

このように二つの方法が考えられますが,もしも成分ごとの平均や分散を求めるといった処理も行いたければ,最初のやり方で inject メソッドを使うのがよいでしょう.