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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

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

Q&A

解決済

4回答

2115閲覧

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

kintarock777

総合スコア34

Ruby

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

0グッド

0クリップ

投稿2017/09/19 21:20

配列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

よろしくお願いします

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

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

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

Ruby

1ary1 = %w(a b c) 2ary2 = %w(b c d) 3ary3 = ary1 & ary2 4ary4 = ary1 | ary2 5 61.upto(4) do |i| 7 p eval("ary#{i}") 8end

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

Ruby

1ary1 = %w(a b c) 2ary2 = %w(b c d) 3ary3 = ary1 & ary2 4ary4 = ary1 | ary2 5 61.upto(4) do |i| 7 p binding.local_variable_get("ary#{i}") 8end

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

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

Ruby

1ary = [] 2ary[1] = %w(a b c) 3ary[2] = %w(b c d) 4ary[3] = ary[1] & ary[2] 5ary[4] = ary[1] | ary[2] 6 71.upto(4) do |i| 8 p ary[i] 9end

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

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

投稿2017/09/19 22:19

raccy

総合スコア21735

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kintarock777

2017/09/20 12:18

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

0

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

x.rb

ruby

1ary1 = %w(a b c) 2ary2 = %w(b c d) 3ary3 = ary1 & ary2 4ary4 = ary1 | ary2 5 6arys = [ary1, ary2, ary3, ary4] 7 8arys.each do |ary| 9 p ary 10end 11 12puts 13arys_hash = { 14 ary1: ary1, 15 ary2: ary2, 16 ary3: ary3, 17 ary4: ary4, 18} 191.upto(4) do |i| 20 name = "ary#{i}".to_sym # 変数名を生成する 21 p arys_hash[name] # 変数名をキーにして、値を引ぱってくる 22end

実行例
イメージ説明

投稿2017/09/20 21:39

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kintarock777

2017/09/21 12:27 編集

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_### ~ の部分が、変数にするみたいなものがあれば、 最初に自分が書いたコードで何とかなるかなと思ったのですが、 やはりそういうものは、存在しないのでしょうか?
guest

0

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

xx.rb

ruby

1def value_of(binding, str) 2 binding.local_variable_get(str) 3end 4 5def arys 6 ary1 = %w[a b c] 7 ary2 = %w[b c d] 8 ary3 = ary1 & ary2 9 ary4 = ary1 | ary2 10 x = 1 11 y = { ary1: ary1 } 12 binding 13end 14 151.upto(4) do |i| 16 p value_of(arys, "ary#{i}") 17end 18 19puts 20arys.local_variables.each do |v| 21 puts "#{v} = #{value_of(arys, v)}" 22end

実行例
イメージ説明

投稿2017/09/22 12:54

編集2017/09/23 09:06
katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kintarock777

2017/09/22 23:31

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

2017/09/23 09:10

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

0

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

投稿2017/09/19 22:28

編集2017/09/19 22:29
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kintarock777

2017/09/20 12:25

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問