前書き
Arraysを使用すると、プログラム内のデータのリストを表すことができます。 配列にデータが格納されたら、並べ替え、重複の削除、順序の反転、配列のセクションの抽出、または特定のデータの配列の検索を行うことができます。 配列をhttps://www.digitalocean.com/community/tutorials/how-to-work-with-strings-in-ruby[string]に変換し、データの配列を別の配列に変換して、ロールアップすることもできます単一の値への配列。
このチュートリアルでは、配列に保存されたデータを操作するためにRubyが提供する最も実用的な方法のいくつかを調べます。
このチュートリアルを完了すると、感嘆符( !
)で終わるメソッドがいくつか表示されます。 これらのメソッドには、元の値の変更や例外の発生などの副作用がよくあります。 このチュートリアルで使用する多くのメソッドには、この接尾辞が付いた関連メソッドがあります。
また、疑問符( ?
)で終わるメソッドに遭遇します。 これらのメソッドはブール値を返します。
これらは、Ruby全体で使用される命名規則です。 プログラムレベルで強制されるものではありません。メソッドに何が期待できるかを特定するための別の方法です。
要素にアクセスするいくつかの方法を見て、配列メソッドの調査を始めましょう
要素へのアクセス
チュートリアルhttps://www.digitalocean.com/community/tutorials/how-to-work-with-arrays-in-ruby[Rubyで配列を操作する方法]を既に実行している場合は、アクセスできることがわかります。次のように、ゼロから始まるインデックスを使用する個々の要素:
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sharks[0] # "Tiger"
sharks[1] # "Great White"
sharks[-1] # "Angel"
また、 `+ first `メソッドと ` last +`メソッドを使用して、配列の最初と最後の要素を取得できることを思い出してください。
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sharks.first # "Tiger"
sharks.last # "Angel"
最後に、存在しない要素にアクセスすると、 `+ nil `を取得します。 ただし、代わりにエラーを取得する場合は、 ` fetch +`メソッドを使用します。
sharks.fetch(42)
OutputIndexError: index 42 outside of array bounds: -4...4
エラーを発生させるのではなく、独自のデフォルトを指定する場合は、それも行うことができます。
sharks.fetch(42, "Nope") # "Nope"
次に、配列から複数の要素を取得する方法を見てみましょう。
複数の要素を取得する
単一の要素だけでなく、配列から値のサブセットを取得したい場合があります。
開始インデックスを指定し、その後に必要な要素の数を指定すると、それらの値を含む新しい配列が取得されます。 たとえば、次のように `+ sharks +`配列から中央の2つのエントリを取得できます。
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sharks[1,2] # ["Great White", "Hammerhead"]
インデックス + 1 +
、つまり `" Great White "`から開始し、 `+ 2 `要素が必要であることを指定し、 `" Great White "`と `を含む新しい配列を取得します。 +「ハンマーヘッド」 `。
`+ slice +`メソッドを使用して同じことを行うことができます。
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sharks.slice(1,2) # ["Great White", "Hammerhead"]
`+ slice `メソッドも新しい配列を返し、元の配列は変更されません。 ただし、 ` slice!+`メソッドを使用すると、元の配列も変更されます。
`+ take +`メソッドを使用すると、配列の先頭から指定された数のエントリを取得できます。
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sharks.take(2) # ["Tiger", "Great White"]
特定の配列ではなく、配列からランダムな値を取得したい場合があります。 方法を調べてみましょう。
配列からランダムエントリを取得する
あなたは偶然のゲームに取り組んでいるか、コンテストの勝者を選ぶプログラムを書いているかもしれません。 これらの種類のものには、ある種のランダムな値が必要です。 一般的な解決策は、可能な選択肢を配列に入れて、ランダムインデックスを選択することです。
配列からランダムな要素を取得するには、 `+ 0 `と配列の最後のインデックスの間にランダムなインデックスを生成し、それを値として取得するためのインデックスとして使用できますが、もっと簡単な方法があります: ` sample +`メソッドは、配列からランダムなエントリを取得します。
これを使用して、ストック回答の配列からランダムな回答を取得し、マジック8ボールゲームのプリミティブバージョンを作成します。
8ball.rb
answers = ["Yes", "No", "Maybe", "Ask again later"]
print answers.sample
OutputMaybe
`+ sample +`メソッドは、ランダムエントリの配列を返す引数も受け入れるため、複数のランダムエントリが必要になった場合は、必要な番号を指定するだけです。
random_sharks.rb
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
sample = sharks.sample(2)
print sample
Output["Whale", "Great White"]
次に、配列内の特定の要素を見つける方法を見てみましょう。
要素の検索とフィルタリング
配列内の特定の要素を探している場合、通常、探しているものが見つかるまで要素を繰り返し処理します。 しかし、Ruby配列には、配列を検索するプロセスを簡素化するために特別に設計されたいくつかのメソッドが用意されています。
要素が存在するかどうかだけを確認したい場合は、指定されたデータが配列の要素である場合に `+ true `を返す ` include?+`メソッドを使用できます。
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
sharks.include? "Tiger" # true
["a", "b", "c"].include? 2 # false
ただし、 `+ include?+`には完全一致が必要なので、単語の一部を探すことはできません。
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
sharks.include? "Tiger" # true
sharks.include? "tiger" # false
sharks.include? "ti" # false
`+ find +`メソッドは、指定した条件に一致する配列の最初の要素を見つけて返します。
たとえば、文字「+ a 」を含む「 sharks 」配列の最初のエントリを識別するには、「 each +」メソッドを使用して各エントリを比較し、次のように最初のエントリが見つかったら反復を停止できます。
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
result = nil
sharks.each do |shark|
if sharks.include? "a"
result = shark
break
end
end
または、 `+ find +`メソッドを使用して同じことを行うこともできます。
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
result = sharks.find {|item| item.include?("a")}
print result
OutputHammerhead
`+ find `は、配列内の各要素に指定したブロックを実行します。 ブロックの最後の式が「 true 」と評価された場合、「 find 」メソッドは値を返し、反復を停止します。 すべての要素を反復処理しても何も見つからない場合は、「 nil +」を返します。
`+ select +`メソッドは同様に機能しますが、単一の値を返して停止するのではなく、条件に一致するすべての要素を含む新しい配列を作成します。
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
results = sharks.select {|item| item.include?("a")}
print results
Output["Hammerhead", "Great White", "Whale"]
`+ reject `メソッドは、条件に一致しない要素を含む新しい配列を返します。 不要な要素を削除するフィルターと考えることができます。 以下は、文字「 a +」を含むすべてのエントリを拒否する例です。
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
results = sharks.reject {|item| item.include?("a")}
print results
Output["Tiger"]
`+ select `と ` reject `は両方とも新しい配列を返し、元の配列は変更しません。 ただし、 ` select!`メソッドと ` reject!+`メソッドを使用すると、元の配列が変更されます。
`+ find_all `メソッドは ` select `のエイリアスですが、 ` find_all!+`メソッドはありません。
次に、配列の値を並べ替える方法を見てみましょう。
配列の並べ替え
データの並べ替えは一般的な方法です。 名前のリストをアルファベット順に並べるか、数字を最小から最大に並べ替える必要がある場合があります。
Ruby配列には、配列内の要素の順序を逆にすることができる `+ reverse `メソッドがあります。 すでに整理されているデータのリストがある場合、要素を反転させるための簡単な方法は「 reverse +」です:
sharks = ["Angel", "Great White", "Hammerhead", "Tiger"]
reversed_sharks = sharks.reverse
print reversed_sharks
Output["Tiger", "Hammerhead", "Great White", "Angel"]
`+ reverse `メソッドは新しい配列を返し、元の配列を変更しません。 代わりに元の配列を変更する場合は、 ` reverse!+`メソッドを使用します。
ただし、配列を逆にすることは、常にデータを並べ替える最も効率的または実用的な方法とは限りません。 `+ sort +`メソッドを使用して、配列内の要素を好みの方法で並べ替えます。
文字列または数字の単純な配列の場合、 `+ sort +`メソッドは効率的で、探している結果が得られます。
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sorted_sharks = sharks.sort
print sorted_sharks
Output["Angel", "Great White", "Hammerhead", "Tiger"]
ただし、物事を別の方法で並べ替えるには、 `+ sort `メソッドにその方法を伝えます。 ` sort +`メソッドは、配列内の要素にアクセスできるRubyブロックを受け取り、それらを比較できるようにします。
比較を行うには、よく_spaceship operator_と呼ばれる_comparison operator_( + <⇒ +
)を使用します。 この演算子は2つのRubyオブジェクトを比較し、左側のオブジェクトが小さい場合は「+ -1 」、オブジェクトが同じ場合は「+0」、左側のオブジェクトが大きい場合は「1」を返します。
1 <=> 2 # -1
2 <=> 2 # 0
2 <=> 1 # 1
Rubyの「+ sort 」メソッドは、「-1 」、「 0+」、または「1」を返す必要のあるブロックを受け入れます。これらのブロックを使用して、配列内の値を並べ替えます。
以下は、配列内のエントリを明示的に比較して昇順で並べ替える例です。
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sorted_sharks = sharks.sort{|a,b| a <=> b }
print sorted_sharks
`+ a `変数と ` b +`変数は、比較される配列内の個々の要素を表します。 結果は次のようになります。
Output["Angel", "Great White", "Hammerhead", "Tiger"]
サメを逆順に並べ替えるには、比較のオブジェクトを逆にします。
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sorted_sharks = sharks.sort{|a,b| b <=> a }
print sorted_sharks
Output["Tiger", "Hammerhead", "Great White", "Angel"]
`+ sort +`メソッドは、整数、浮動小数点数、文字列などの単純なデータ型を含む配列に最適です。 ただし、配列にさらに複雑なオブジェクトが含まれる場合は、もう少し作業が必要になります。
ハッシュの配列は次のとおりです。各ハッシュはサメを表します。
sharks = [
{name: "Hammerhead"},
{name: "Great white"},
{name: "Angel"}
]
これを `+ sort`でソートするのは簡単ではありません。 配列で `+ sort +`を呼び出すと失敗します。
sharks.sort
OutputArgumentError: comparison of Hash with Hash failed
比較を行うために、比較したい内容を `+ sort `に伝える必要があります。 そこで、ハッシュ内の `:name +`キーの値を比較します。
sorted_sharks.sort{|a, b| a[:name] <=> b[:name]}
print sorted_sharks
Output[{:name=>"Angel"}, {:name=>"Great white"}, {:name=>"Hammerhead"}]
より複雑な構造で作業している場合は、代わりに、より効率的なアルゴリズムを使用して並べ替える「+ sort_by 」メソッドをご覧ください。 ` sort_by +`は、配列内の現在の要素への参照である1つの引数のみを必要とするブロックを取ります。
sharks = [
{name: "Hammerhead"},
{name: "Great white"},
{name: "Angel"}
]
sorted_sharks = sharks.sort_by{|shark| shark[:name] }
print sorted_sharks
Output[{:name=>"Angel"}, {:name=>"Great white"}, {:name=>"Hammerhead"}]
`+ sort_by `メソッドはhttps://en.wikipedia.org/wiki/Schwartzian_transform[Schwartzian transform]を実装します。これは特定のキーの値に基づいてオブジェクトを比較するのに最適なソートアルゴリズムです。 したがって、オブジェクトのコレクションを比較するときは、より効率的であるため、 ` sort_by +`を使用していることに気付くでしょう。
`+ sort `と ` sort_by `は両方とも新しい配列を返し、元の配列はそのまま残します。 元の配列を変更したい場合は、代わりに ` sort!`と ` sort_by!+`を使用してください。
値のソートに加えて、重複を取り除くこともできます。
重複する要素を削除する
重複するデータのリストを取得する場合があります。 配列を反復処理して重複を除外することもできますが、Rubyの「+ uniq 」メソッドを使用すると簡単になります。 ` uniq +`メソッドは、重複する値をすべて削除した新しい配列を返します。
[1,2,3,4,1,5,3].uniq # [1,2,3,4,5]
2つのデータセットをマージすると、重複することがあります。 次の2つのサメの配列を使用します。
sharks = ["Tiger", "Great White"]
new_sharks = ["Tiger", "Hammerhead"]
それらを一緒に追加すると、重複したエントリが取得されます。
sharks + new_sharks
# ["Tiger", "Great White", "Tiger", "Hammerhead"]
「+ uniq 」を使用して重複を削除することもできますが、それらを完全に導入しないでください。 配列を一緒に追加する代わりに、パイプ演算子 ` | +`を使用して、配列をマージします。
sharks | new_sharks
# ["Tiger", "Great White", "Hammerhead"]
Ruby配列は減算もサポートしています。つまり、新しい値のみを取得するために、「+ sharks 」から「 new_sharks +」を減算できます。
sharks = ["Tiger", "Great White"]
new_sharks = ["Tiger", "Hammerhead"]
sharks - new_sharks # ["Great White"]
次に、各要素の値を操作する方法を見てみましょう。
データの変換
`+ map `メソッドとそのエイリアス ` collect +`は、配列の内容を変換できます。つまり、配列内の各要素に対して操作を実行できます。
たとえば、 `+ map +`を使用して配列内の各エントリで算術演算を実行し、新しい値を含む新しい配列を作成できます。
numbers = [2,4,6,8]
# square each number
squared_numbers = numbers.map {|number| number * number}
print squared_numbers
`+ squared_numbers +`変数は、元の数値の配列であり、2乗されます。
[4, 16, 36, 64]
`+ map +`は、Webアプリケーションで配列をHTMLドロップダウンリストの要素に変換するためによく使用されます。 これがどのように見えるかを非常に簡略化したバージョンを次に示します。
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
options = sharks.map {|shark| "<option>#{shark}</option>"}
print options
+ options +`配列の各サメは、 `+ <option> </ option> +
HTMLタグでラップされています:
["<option>Hammerhead</option>", "<option>Great White</option>", "<option>Tiger</option>", "<option>Whale</option>"]
`+ map `は新しい配列を返し、元の配列は変更されません。 ` map!`を使用すると、既存の配列が変更されます。 そして、 ` map `には ` collect +`というエイリアスがあることに注意してください。 一貫性を保ち、どちらか一方をコードで使用する必要があります。
`+ map +`は新しい配列を返すので、配列を変換してさらに操作したり、文字列に変換することもできます。 次を見てみましょう。
配列を文字列に変換する
Rubyのすべてのオブジェクトには、オブジェクトを文字列に変換する `+ to_s `メソッドがあります。 これは、 ` print `ステートメントが使用するものです。 ` sharks +`の配列を考えると:
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
`+ to_s +`メソッドを呼び出すと、次の文字列が作成されます。
"[\"Hammerhead\", \"Great White\", \"Tiger\", \"Whale\"]"
これはデバッグには適していますが、実際のプログラムではあまり役に立ちません。
`+ join `メソッドは配列を文字列に変換しますが、要素をどのように組み合わせるかをより細かく制御できます。 ` join +`メソッドは、セパレータとして使用する文字を指定する引数を取ります。 サメの配列をスペースで区切られたサメの名前の文字列に変換するには、次のようにします。
shark_join.rb
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
result = sharks.join(" ")
print result
OutputHammerhead Great White Tiger Whale
各サメの名前をコンマで区切る場合は、カンマとスペースを区切り文字として使用します。
shark_join.rb
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
result = sharks.join(", ")
print result
OutputHammerhead, Great White, Tiger, Whale
`+ join +`メソッドに引数を指定しない場合、文字列は取得されますが、区切り文字はありません:
shark_join.rb
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
result = sharks.join
print result
OutputHammerheadGreat WhiteTigerWhale
`+ map `とともに ` join `を使用すると、データの配列を出力にすばやく変換できます。 ` map `を使用してデータ内の各要素を変換し、次に ` join `を使用してすべてを印刷可能な文字列に変換します。 ` sharks `配列をHTML要素の配列に変換する例を覚えていますか? 同じ例をもう一度示しますが、今回は ` join +`を使用して、要素の配列を区切り文字として改行文字を含む文字列に変換します。
map.rb
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
options = sharks.map {|shark| "<option>#{shark}</option>"}
output = options.join("\n")
print output
Output<option>Hammerhead</option>
<option>Great White</option>
<option>Tiger</option>
<option>Whale</option>
配列を文字列に変換する代わりに、そのコンテンツの合計を取得するか、単一の値になる他の種類の変換を実行することもできます。 それは次です。
配列を単一の値に減らす
一連のデータを操作しているときに、データを合計などの単一の値にまとめる必要がある場合があります。 これを行う1つの方法は、変数と `+ each +`メソッドを使用することです。
result = 0
[1, 2, 3].each {|num| result += num}
print result
Output6
代わりに `+ reduce `メソッドを使用してこれを行うことができます。 ` reduce +`メソッドは配列を繰り返し処理し、各要素に対してバイナリ演算を実行することで現在の合計を保持します。
`+ reduce +`メソッドは、結果の初期値と、結果への参照と現在の要素への参照という2つのローカル値を持つブロックを受け入れます。 ブロック内で、最終結果を計算するロジックを指定します。
配列を合計したいので、結果を「0」に初期化し、現在の値をブロックの結果に追加します。
output = [1,2,3].reduce(0) {|result, current| result += current }
print output
Output6
結果を `+ 0 +`に初期化する場合、引数を省略してブロックを渡すことができます。 これにより、結果が配列の最初の値に自動的に設定されます。
output = [1,2,3].reduce {|result, current| result += current }
print output
Output6
`+ reduce `メソッドは、_binary method_、または引数として別のオブジェクトを受け入れる1つのオブジェクトのメソッドも指定します。これは、配列の各エントリに対して実行されます。 ` reduce +`はその結果を使用して単一の値を作成します。
Rubyで「2 + 2」を記述する場合、実際には整数「2」で「+」メソッドを呼び出します。
2.+(2) # 4
Rubyはいくつかの_構文的シュガー_を使用するため、「+ 2 + 2+」と表現できます。
`+ reduce `メソッドでは、名前をシンボルとして渡すことでバイナリメソッドを指定できます。 つまり、 `:+`を ` reduce +`メソッドに渡して配列を合計できます。
output = [1, 2, 3].reduce(:+)
print output
Output6
ただし、 `+ reduce `を使用して、単なる数字のリストを追加するだけではありません。 これを使用して値を変換できます。 ` reduce +`は配列を単一の値に減らすことを忘れないでください。 しかし、単一の値を別の配列にすることはできないというルールはありません。
整数に変換する必要がある値のリストがあるとしましょう。 ただし、整数に変換できる値のみが必要です。
+ rejects`を使用して数値以外の値を破棄し、
+ map`を使用して残りの値を整数に変換できます。 しかし、 `+ reduce +`を使用してすべてを1ステップで実行できます。 方法は次のとおりです。
初期化値として空の配列を使用します。 次に、ブロックで、 `+ Integer `メソッドを使用して現在の値を整数に変換します。 値を整数に変換できない場合、 ` Integer `は例外を発生させます。例外はキャッチして、値に ` nil +`を割り当てることができます。
次に、値を取得して配列に入れますが、それが「+ nil +」でない場合のみです。
コードは次のようになります。 これを試してみてください。
convert_array_of_values.rb
values = ["1", "2", "a", "3"]
integers = values.reduce([]) do |array, current|
val = Integer(current) rescue nil
array.push(val) unless val.nil?
array
end
print integers
Output[1,2,3]
単一の値に変換する必要がある要素のリストがあるときはいつでも、 `+ reduce +`でそれを解決できるかもしれません。
結論
このチュートリアルでは、いくつかの方法を使用して配列を操作しました。 個々の要素を取得し、配列を検索して値を取得し、要素を並べ替え、データを変換して、新しい配列、文字列、および合計を作成しました。 これらの概念を適用して、Rubyでの多くの一般的なプログラミングの問題を解決できます。
Rubyでデータを操作する方法を引き続き検討するには、これらの関連チュートリアルを参照してください。