質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.75%

  • Ruby

    7002questions

    Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

配列の名前の一部をさらに変数にして、繰り返し処理をしたい

解決済

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 728

kintarock777

score 11

配列ary1,ary2,ary3,ary4があり、数字の部分を変数にして
繰り返ししょりがしたいです。

ary1 = %w(a b c)
ary2 = %w(b c d)
ary3 = ary1 & ary2
ary4 = ary1 | ary2


1.upto(4) do |i|
    p ary#"i"  # <=この部分のコードの書き方がわかりません
          # 繰り返しで、p ary1  ~ p ary4  の処理をしたい
end


よろしくお願いします

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+3

PHPの可変変数のようなことをとしたいと言うことでしょうか?残念ながら、最初は誰もがほしがるこの可変変数は、初心者に十分なぐらい配慮したPHPぐらいでしか使えません。Rubyを始めたとした他の言語は同じ事ができないと言うことです。(少なくとも、私はPHP以外で可変変数がある言語を知りません。初心者に冷たいのか、そういう発想はするなと初心者を諭しているのか、どちらかだと思います。)

では、どうするかというと、最も単純なのはeval()を使うことです。

ary1 = %w(a b c)
ary2 = %w(b c d)
ary3 = ary1 & ary2
ary4 = ary1 | ary2

1.upto(4) do |i|
  p eval("ary#{i}")
end

しかし、"eval is evil"と言われるぐらい、eval()はなるべく避けるべきとされています(理由は長くなるので説明はしません)。では、eval()を使わないならどうするかというと、現在の場所のローカル変数を探すlocal_variable_getを使うという方法があります。

ary1 = %w(a b c)
ary2 = %w(b c d)
ary3 = ary1 & ary2
ary4 = ary1 | ary2

1.upto(4) do |i|
  p binding.local_variable_get("ary#{i}")
end

eval()より安全ですが、本来のアクセスに比べると冗長でなんか面倒なことをしている印象を受けます。

最後に、みんなこういうときはどうしているのかというと、変数名を連番にして作るのでは無く、一つの配列を作って、そこに入れていくという手法を使います。

ary = []
ary[1] = %w(a b c)
ary[2] = %w(b c d)
ary[3] = ary[1] & ary[2]
ary[4] = ary[1] | ary[2]

1.upto(4) do |i|
  p ary[i]
end

大きく番号が飛んで配列だと無駄が多ければ、Hashでもいいでしょう。

(トランスパイルなどのコードの自動生成を除けば)変数名に連番を付けること自体が悪い作法と言われています。なぜなら、一般に変数名は、その名前そのものに意味があるべきとされるからです。ary1ary2のaryは配列を意味するとわかりますが、1や2に何の意味を見いだせないのであれば付けるべきではありません。単に複数の変数をまとめて取り扱いたいなら、一つの配列に入れてしまう方が良いでしょう。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/20 21:18

    回答ありがとうございます。
    変数の連番ではなく、配列を作ってそこに入れるんですねぇ
    発想というか、応用力というか、とにかくやられたぁって感じで、
    感動しました。
    実際の現場では、きっとそういう力が必要になってくるのでしょうね、
    これから身に着けていきたいと思います。
    evalや、local_variable_getも、知らなかったメソッド?なので、良し悪しはまた別にして知識としては大変参考になりました。
    また、よろしくお願いします。

    キャンセル

+1

raccy さんの回答で十分ですが、実際に Hash をつかったコード等を示してみます。

x.rb

ary1 = %w(a b c)
ary2 = %w(b c d)
ary3 = ary1 & ary2
ary4 = ary1 | ary2

arys = [ary1, ary2, ary3, ary4]

arys.each do |ary|
  p ary
end

puts
arys_hash = {
  ary1: ary1,
  ary2: ary2,
  ary3: ary3,
  ary4: ary4,
}
1.upto(4) do |i|
  name = "ary#{i}".to_sym # 変数名を生成する
  p arys_hash[name]       # 変数名をキーにして、値を引ぱってくる
end


実行例
イメージ説明

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/21 21:26 編集

    katoyさん、いつも回答ありがとうございます。
    今回も早速試してみました。前半のコードは個人的にはすごく好きですねぇ、
    というか、なぜ先に思いつかなかったかと思うと悔しいです(笑)
    eachを使っているところもシンプルになってよいなぁ、と感じました。
    後半のhashを使ったやり方は初めてだったので、大変参考になりました。
    さらにuptoからeachに書き換えてみたところ、表示内容が

    ["a", "b", "c"]
    ["b", "c", "d"]
    ["b", "c"]
    ["a", "b", "c", "d"]
    から

    [:ary1, ["a", "b", "c"]]
    [:ary2, ["b", "c", "d"]]
    [:ary3, ["b", "c"]]
    [:ary4, ["a", "b", "c", "d"]]

    に変わり、こちらも面白いですねぇ。

    あと name = "ary#{i}".to_sym  の行の
    ~ .to_### ~ の部分が、変数にするみたいなものがあれば、
    最初に自分が書いたコードで何とかなるかなと思ったのですが、
    やはりそういうものは、存在しないのでしょうか?

    キャンセル

0

僕も過去に同じ質問をしました!
参考になればいいのですが
https://teratail.com/questions/90668

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/20 21:25

    回答ありがとうございます。
    初心者の質問ですみませんでした(笑)
    みなさん、同じようなところで立ち止まるのだなぁと、少しホッとしました。過去の質問の回答読ませていただきました。
    難しくてよくわからないところもありましたが、evalが危険みたいなことは、とりあえず覚えておきます。
    また、過去質問を繰り返してしまうかもしれませんが、その時はまた教えてください。
    ありがとうございました

    キャンセル

0

raccy さんの回答で十分ですが、eval や local_variable_get をちょっと隠してみたコードを示します。

xx.rb

def value_of(binding, str)
  binding.local_variable_get(str)
end

def arys
  ary1 = %w[a b c]
  ary2 = %w[b c d]
  ary3 = ary1 & ary2
  ary4 = ary1 | ary2
  x = 1
  y = { ary1: ary1 }
  binding
end

1.upto(4) do |i|
  p value_of(arys, "ary#{i}")
end

puts
arys.local_variables.each do |v|
  puts "#{v} = #{value_of(arys, v)}"
end


実行例
イメージ説明

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/23 08:31

    回答ありがとうございます。
    早速試してみました。コードの書き方の幅がひろがりますねぇ。
    もともと、~ def arys ~が 現在の場所に存在するときに、
    それを使ってしまおうという考え方でしょうか?

    それとも、evalやlocal_variable_getを使っているところを
    見られたくないから、隠してしまうのでしょうか?(笑)

    キャンセル

  • 2017/09/23 18:10

    質問文のコードでは、変数名 ary1 .. ary4 をしっていて eachを回していました。この回答のコードでは変数名を動的に取得する例も示してみました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.75%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Ruby

    7002questions

    Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。