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

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

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

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

Q&A

解決済

3回答

1681閲覧

【Ruby】each_with_index について

nimbus1978

総合スコア14

Ruby

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

0グッド

3クリップ

投稿2015/05/11 04:59

編集2015/05/11 05:00

A = ['a', 'b', 'c', 'd', 'e']
B = [[], [], [], [], []]

という二つの配列において、Aのそれぞれの要素をBに代入し

B = [['a'], ['b'], ['c'], ['d'], ['e']] としたかったので

A.each_with_index do |n, i|
B[i] << n
end
としたところ、

irb(main)> B
=> [["a", "b", "c", "d", "e"], ["a", "b", "c", "d", "e"], ["a", "b", "c", "d", "e"], ["a", "b", "c", "d", "e"], ["a", "b", "c", "d", "e"]]

になってしまいました。

何故だか理解ができません。
原因がおわかりになる方いらっしゃいましたら、教えていただけますでしょうか。
よろしくお願いします。

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

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

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

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

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

guest

回答3

0

ベストアンサー

B配列をB = Array.new(5, [])というコードで作っていませんか?
これをB = [[], [], [], [], []]もしくはB = Array.new(5){[]}に書き換えるとうまくいくと思います。
指摘がずれていたらすみません……。

投稿2015/05/11 05:39

penguinshunya

総合スコア140

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

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

nimbus1978

2015/05/11 05:42

まさに、ご指摘のとおりに Bを作っていました。 書き換えたらうまくいきました。  しかし、何故でしょうか? : D 不思議です
jun68ykt

2015/05/11 05:43

なるほど!勉強になりました。
nimbus1978

2015/05/11 05:52

A, Bの生成からコードを書いておくべきでした。 お手数をおかけしました。
maisumakun

2015/05/11 05:57

配列、ハッシュ、文字列など、書き換え可能なオブジェクトをArrayの初期値にセットすると、コピーではなくて、同じオブジェクトに対する参照が入ってしまいます。 上の回答にあるようにブロックで指定すると、要素1つごとに新たな配列を生成するようになります。
penguinshunya

2015/11/17 13:21 編集

うーん、この辺は説明が難しいんですが、 B = Array.new(5, []) というコードだと、要素としての配列は1個しか作られません。 たとえ 5 を 100 や 200 に書き換えたとしても、作られる配列は1個だけです。 しかし、 B = Array.new(5){[]} というコードでは、要素としての配列が5個作られます。 そして 5 を 100 に書き換えると、配列も100個作られます。 要素として作られる配列が1つだけなので B[0] も B[1] も同じ配列を指します。 つまりnimbus1978さんの書いたコードと次のコードは全く同じ意味になります。 A.each_with_index do |n, i| B[0] << n end
nimbus1978

2015/05/11 06:31

なるほど、そういうことだったんですね。 参照する要素がひとつだけだったとは。 とてもわかりやすかったです。  ありがとうございました。
nimbus1978

2015/05/11 07:02

改めてマニュアルを見ると、同じnewでも、各々の記法で、それぞれ仕様が違うんですね。 勉強になりました。
guest

0

こんにちは。

私のほうの手元にある環境で、当該のソース、question9676.rb
を作成して実行してみたログが以下です。

[ykt68@sakura-vps] cat /etc/redhat-release
CentOS release 6.6 (Final)
[ykt68@sakura-vps] date
2015年 5月 11日 月曜日 14:23:10 JST
[ykt68@sakura-vps] cat question9676.rb

lang

1a = ['a', 'b', 'c', 'd', 'e'] 2b = [[], [], [], [], []] 3 4p b 5 6a.each_with_index do |n, i| 7 b[i] << n 8end 9 10p b

[ykt68@sakura-vps] ruby -v
ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-linux]
[ykt68@sakura-vps] ruby question9676.rb
[[], [], [], [], []]
[["a"], ["b"], ["c"], ["d"], ["e"]]
[ykt68@sakura-vps]

恐縮ながら念のため、ひとこと申し添えますと、上記のコードの

lang

1 b[i] << n

の n をうっかり a にしてしまっていて、

lang

1 b[i] << a

となっていると、結果は

[ykt68@sakura-vps] ruby question9676.rb

[[], [], [], [], []]
[[["a", "b", "c", "d", "e"]], [["a", "b", "c", "d", "e"]], [["a", "b", "c", "d", "e"]], [["a", "b", "c", "d", "e"]], [["a", "b", "c", "d", "e"]]]

となります。
ご質問の状況とは少し違いますが、
参考になれば幸いです。

投稿2015/05/11 05:34

編集2015/05/11 05:36
jun68ykt

総合スコア9058

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

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

nimbus1978

2015/05/11 05:40

ご回答ありがとうございます。 参考にさせていただき、再度たしかめたのですが、 やはり同じ結果になりました。 
guest

0

私の環境では以下のように意図された通りの動作になります。

$ pry [1] pry(main)> A = ['a', 'b', 'c', 'd', 'e'] => ["a", "b", "c", "d", "e"] [2] pry(main)> B = [[], [], [], [], []] => [[], [], [], [], []] [3] pry(main)> A.each_with_index do |n, i| [3] pry(main)* B[i] << n [3] pry(main)* end => ["a", "b", "c", "d", "e"] [4] pry(main)> B => [["a"], ["b"], ["c"], ["d"], ["e"]]

A,Bのように大文字で記述されたものは変数ではなく定数として扱われるため、恐らくこの操作の前に既にBに値が設定されていたのではないでしょうか?

プログラム内で値を書き換える変数にはa,bのように小文字から始まるものを使用しましょう。

投稿2015/05/11 05:12

ironsand

総合スコア91

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

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

nimbus1978

2015/05/11 05:19

アドバイスありがとうございます。 変数は小文字でしたね。 しかしA, Bを小文字に置き換えてみても、同じ結果になります。
nimbus1978

2015/05/11 05:22

私のrubyのバージョンは 2.2.0p0 です
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問