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

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

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

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

2回答

2469閲覧

文字列の中で、繰り返し使われている文字の数を出すメソッドのコードに関する質問です。

H-JURI

総合スコア42

Ruby

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2015/11/14 11:09

Rubyをベースにプログラミングを学んでいる超初心者です。繰り返し使われている文字の数を出すメソッドを作れ。という課題の解答コードの配列の部分が理解できません。

Ruby

11. def num_repeats(string) 22. counts = [] 33. 44. str_idx = 0 55. while str_idx < string.length 66. letter = string[str_idx] 77. 88. counts_idx = 0 99. while counts_idx < counts.length 10 1110. if counts[counts_idx][0] == letter ・・・・・① 1211. counts[counts_idx][1] += 1 1312. break 1413. end 15 1614. counts_idx += 1 1715. end 1816. 1917. if counts_idx == counts.length 2018. # didn't find this letter in the counts array; count it for the 2119. # first time 2220. counts.push([letter, 1]) 2321. end 2422. 2523. str_idx += 1 2624. end 2725. 2826. num_repeats = 0 2927. counts_idx = 0 3028. while counts_idx < counts.length 31 3229. if counts[counts_idx][1] > 1 3330. num_repeats += 1 3431. end 3532. 3633. counts_idx += 1 3734. end 3835. 3936. return num_repeats 4037. end 41# These are tests to check that your code is working. After writing 42# your solution, they should all print true. 43 44puts('num_repeats("abdbc") == 1: ' + (num_repeats('abdbc') == 1).to_s) 45# one character is repeated 46puts('num_repeats("aaa") == 1: ' + (num_repeats('aaa') == 1).to_s) 47puts('num_repeats("abab") == 2: ' + (num_repeats('abab') == 2).to_s) 48puts('num_repeats("cadac") == 2: ' + (num_repeats('cadac') == 2).to_s) 49puts('num_repeats("abcde") == 0: ' + (num_repeats('abcde') == 0).to_s)

lang

1num_repeats("abdbc") == 1: true 2num_repeats("aaa") == 1: true 3num_repeats("abab") == 2: true 4num_repeats("cadac") == 2: true 5num_repeats("abcde") == 0: true

①に関してなのですが、counts[counts_idx][0]というのが理解できません。
8.において
counts_idx = 0
としているので、counts[0][0]になり、意味がよくわかりません。。。そもそもcounts[][]とは、
どういった処理をするのでしょうか?調べてもなかなか出てきません。ご教授お願いします!!

num_repeats("abcba")を例とした僕自身の思考を書いておきます。

lang

1num_repeats("abcba") 2 32.で空の配列オブジェクトcountsをつくる 4 5↓str_idx = 0 で、0 < 5(string.length)なので5.へ。 6 7letter = aになる 8 9↓counts_idx = 0 で、0 = 0(counts.length)なので9.のwhileをとばし、17.のifへ。 10 11空のcountsに[ a , 1 ]([ letter , a ])を入れる 12 13↓str_idx = 1になって、1 < 5(string.lengrh)なので繰り返し5.へ。 14 15letter = bになる 16 17↓counts_idx = 0 で、0 < 2(counts.length)なので9.のwhileへ。 18 1910.でのcounts[counts_idx][0]→counts[0][0]→a[0]・・・?←ーー今ここで止まってます。 20

説明がへたくそで大変申し訳ありません。困っているので助けてください。

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

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

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

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

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

guest

回答2

0

解説はkatoyさんが示しているとおりですので、下記は蛇足です。興味があればお読みください。

解答例がRubyとしては悪すぎます。whileで文字列(String)や配列(Array)を回す人はいません。Rubyっぽく素直に書き直すと下記のようになります。

Ruby

1def num_repeats(string) 2 counts = [] 3 4 string.each_char do |letter| 5 found = false 6 counts.each do |pair| 7 if pair[0] == letter 8 pair[1] += 1 9 found = true 10 break 11 end 12 end 13 unless found 14 counts << [letter, 1] 15 end 16 end 17 18 num_repeats = 0 19 counts.each do |pair| 20 if pair[1] > 1 21 num_repeats += 1 22 end 23 end 24 25 return num_repeats 26end

katoyさんが言うように、countsをHashにするとさらに読みやすい物にできます。

なお、num_repeatsは頑張ると一行で書けます。

Ruby

1def num_repeats(string) 2 string.each_codepoint.group_by(&:to_i).each_value.map(&:size).count{|i|i>1} 3end

関数型やLINQとかに慣れている人はこの方がわかりやすいかも知れません。

投稿2015/11/14 13:48

raccy

総合スコア21733

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

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

katoy

2015/11/14 14:48

私は、改善案としては、  string.split('').inject(Hash.new(0)){|hash,c|hash[c] += 1;hash}.delete_if{|k,v| v < 2}.size に相当するコードを示そうと思っていました。 group_by() を使うほうが良さそうですね。 さらに、テストケースに "" (長さ0の文字列) を追加することも言おうと思っていました。
guest

0

ベストアンサー

num_repeats(string) の最後を次のようにしてから、実行させてみてください。
p counts
num_repeats

すると、つぎのような出力になります。

[["a", 1], ["b", 2], ["d", 1], ["c", 1]]
num_repeats("abdbc") == 1: true
[["a", 3]]
num_repeats("aaa") == 1: true
[["a", 2], ["b", 2]]
num_repeats("abab") == 2: true
[["c", 2], ["a", 2], ["d", 1]]
num_repeats("cadac") == 2: true
[["a", 1], ["b", 1], ["c", 1], ["d", 1], ["e", 1]]
num_repeats("abcde") == 0: true

counts という配列はさらに配列になっていて
[0]番目の要素: 文字
[1]番目の要素: 出現回数
となっているのです。

20 行目の counts.push([letter, 1])
は、cuunts に登録されていない文字だったときに、その文字の出現回数 1 という配列を counts に登録しているのです。

このメソッドは 配列よりは Hash をつかったほうが短くかけます。
Hash をつかった方法に是非 挑戦してみてください。
ギブアップしたなら、ここの質問を投げてください。さらにヒントを投稿します。

投稿2015/11/14 11:33

katoy

総合スコア22324

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問