Ruby/配列操作

最終更新: 2016-03-11 (金) 16:47:49 (498d)

このページの内容は http://yakinikunotare.boo.jp/orebase2/ruby/array_ope へ移動しました。

配列操作

目次 Edit

初期化系 Edit

配列を作る Edit

hoge = Array.new();

リテラルで配列を作る Edit

hoge = [1, 2, 3]

メタ情報系 Edit

配列の長さを得る Edit

hoge = [1, 2, 3]
p hoge.size #=> 3

追加系 Edit

末尾に追加する Edit

hoge = Array.new();
hoge << 'aaa'

2つの配列を破壊的に結合する Edit

hoge = [1,2,3]
piyo = [5,6,7]
hoge.concat(piyo)
p hoge #=> [1,2,3,4,5,6]

2つの配列を結合し新たな配列を作る Edit

hoge = [1,2,3]
piyo = [5,6,7]
fuga = hoge + piyo
p fuga #=> [1,2,3,4,5,6]

抽出系 Edit

要素の範囲を指定して抽出 Edit

Rangeを使います

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

先頭要素を取得して先頭要素を削除する Edit

つまりスタック構造の操作ですな

a = [1,2,3]
p a.shift #=> 1
p a.shift #=> 2
p a #[3]

p a.shift #=> 3
p a.shift #=> nil
p a.shift #=> nil

末尾の要素を取得 Edit

hoge = [1, 2, 3]
hoge.last #=> 3

条件に合致する最初の1要素を取得 Edit

hoge = [1, 2, 3]
piyo = hoge.find do |a|
  a == 2
end
p piyo #=>2

条件に合致したすべての要素を配列で取得 Edit

hoge = [1, 2, 3]
piyo = hoge.find_all do |a|
  a >= 2
end
p piyo #=>[2, 3]

find_allはselectって別名も持っているので文脈によって使い分けるといいかもね

削除系 Edit

nilだけを削除する Edit

a = [nil, nil, 123].compact
p a #=> [123]

破壊的なやつもある

a = [nil, nil, 123]
a.compact!
p a #=> [123]

重複を取り除く SQLでいうdistinct Edit

配列から重複要素を取り除くには uniqメソッドを使う

hoge = [1, 2, 2, 3, 3, 2, 1]
hoge = hoge.uniq
p hoge #=> [1, 2, 3]

文字列に対しても同様に可能

uniq!

で破壊的に取り除く

合致する要素を削除 Edit

hoge = [1, 2, 3]
hoge.delete(2)
p hoge #=> [1, 3]

このメソッドでは破壊的に取り除かれる

位置を指定して削除 Edit

hoge = [1, 2, 3]
hoge.delete_at(1)
p hoge #=> [1, 3]

delete_atメソッドの戻りは削除した値で、削除は破壊的に行われる。

最後の要素を削除 Edit

位置を指定して削除の応用

hoge = [1, 2, 3]
hoge.delete_at(-1)
p hoge #=> [1, 2]

ソート系 Edit

安定ソートする Edit

sort_byメソッドをうまく使うとできるっぽ

a = [[1,3],[1,2],[1,1],[2,3],[2,2],[2,1]]
i = 0
a = a.sort_by do |b|
  [b[1], i += 1]
end
i = 0;
a = a.sort_by do |b|
  [b[0], i += 1]
end
p a #=>[[1,1],[1,2],[1,3],[2,1],[2,2],[2,3]]

sort_by Edit

このメソッドが興味深げなので

class Array
  def sort_by
    self.collect { |i| [yield(i), i] }.
       sort {|a,b| a[0] <=> b[0] }.
       collect! {|i| i[1]}
  end
end

定義はこうらしい

処理ブロックをcollectメソッドに渡してる
collectメソッドは配列の各要素に対して処理を行うメソッドになる・・・
今回だと処理は1行だけ〜 これは使われる状況を考えないとわかりにくい

a = [3, 2, 1]
a.sort_by do |b|
  b
end

こんな場合を想定すると・・・
yeildは

def yeild(b)
  b
end

このように定義されるので そしてcollectは各配列に処理されるのでiには3,2,1が順に入ることになる
つまりcollectメソッドは

[3, 3]
[2, 2]
[1, 1]

というメソッドを内部で打ち出すことになる
結果を配列として結合するので

[[3, 3],[2, 2],[1, 1]]

まずこうなる
そして

[[3, 3],[2, 2],[1, 1]].sort {|a,b| a[0] <=> b[0] }

こいつの実行
sortメソッドが受け取っている処理ブロックは比較対象を2つとって <=> メソッドで比較してます
つまり処理ブロックは-1, 0, 1の値のリターンを期待しています
最初の場合

3 <=> 2

このような状況になる。当然関係性は 3 > 2 なので 値は1
結果

[[1, 1],[2, 2],[3, 3]]

という配列が出来上がる
最後に

[[1, 1],[2, 2],[3, 3]].collect! {|i| i[1]}

結合しなおして

[1, 2, 3]

という配列を作るっている・・・確かにソートされた

そこで安定ソートの例を見ると、処理自体に配列を強制的に作ってリターンしている

a = [[1,3],[1,2],[1,1],[2,3],[2,2],[2,1]]
i = 0
a = a.sort_by do |b|
  [b[1], i += 1]
end

まず各要素....[1, 3],[1, 2]...を突っ込み
その各要素を格納するから

[[3, 1], [1, 3]]
[[2, 2], [1, 2]]
[[1, 3], [1, 1]]

こうなって最終的にはがっちゃんこで

[[[3, 1], [1, 3]], [[2, 2], [1, 2]], [[1, 3], [1, 1]]]

こうなる
そして各要素の先頭要素比較をすることになるので

[3, 1] <=> [2, 2]

こんな比較が行われることになる
配列に対する<=>メソッドは
頭から順に比較していって決着がつくまで評価していくというものなので指定したソート基準値で決まればそれまでだし、そうでなければ次の項目(i += 1で生成した値)で比較を行う。この次の項目っていうのは初期状態の並びを保持しているということなので結果安定ソートになる!

すごい!

Enumerable - Rubyリファレンスマニュアル

ランダムにソートする Edit

つまりシャッフルする

[1,2,3].sort_by{rand}

・・・らしい

集合演算 Edit

RubyのArrayは便利なもんで順番がある箱ではなく値の集合として扱うことができる。

共通部分を削除する 差集合 Edit

−演算子なのでベースは左辺になる。非破壊的

a = [1, 2, 3, 4]
b = [2, 4]
p a - b #=>[1, 3]

共通部分を取り出す 積集合 Edit

a = [1, 2, 3, 4]
b = [2, 4]
p a & b #=>[2, 4]

列挙処理系 Edit

列挙された項目を集める Edit

一言でこの機能を言うのは難しいけど、配列でループしてその中で処理した値を集めてまた配列にするという処理。全要素をあますことなく処理するときに使う。

a = [1,2,3,4,5].collect do |b|
  b * 10
end
p a #=> [10,20,30,40,50]

要素数の増減を伴う処理をやりたいときはfind_allとかselectを使うといいかな

参考サイト Edit

タグ Edit

Tag: Ruby 配列 配列操作 基本 移動済み

リロード   new Edit 凍結 差分 Upload 複製 名前変更   Home Page list Word Search Recent Update バックアップ Referer   Help   最終更新のRSS
Last-modified: 2016-03-11 (金) 16:47:49 (498d)