Techioz Blog

文字列内の最も一般的な単語

概要

私は Ruby を初めて使用するので、文字列内の最も一般的な単語の配列を返すメソッドを作成しようとしています。カウントの高い単語が 1 つある場合は、その単語を返す必要があります。上位カウントに 2 つのワードが並んでいる場合は、両方を配列で返す必要があります。

def most_common(string)
  counts = {}
  words = string.downcase.tr(",.?!",'').split(' ')

  words.uniq.each do |word|
    counts[word] = 0
  end

  words.each do |word|
    counts[word] = string.scan(word).count
  end

  max_quantity = counts.values.max
  max_words = counts.select { |k, v| v == max_quantity }.keys
  puts max_words
end

most_common('a short list of words with some words') #['words']
most_common('Words in a short, short words, lists of words!') #['words']
most_common('a short list of words with some short words in it') #['words', 'short']

解決策

単語の出現数を数える方法が問題です。 with に入っているので二重にカウントされます。

[1] pry(main)> 'with some words in it'.scan('it')
=> ["it", "it"]

ただし、より簡単に実行できます。次のように、 each_with_object 呼び出しを使用して、値のインスタンスの数によって配列の内容をグループ化できます。

counts = words.each_with_object(Hash.new(0)) { |e, h| h[e] += 1 }

これは、配列内の各エントリを調べて、ハッシュ内の各単語のエントリの値に 1 を加えます。

したがって、次のことがうまくいくはずです。

def most_common(string)
  words = string.downcase.tr(",.?!",'').split(' ')
  counts = words.each_with_object(Hash.new(0)) { |e, h| h[e] += 1 }
  max_quantity = counts.values.max
  counts.select { |k, v| v == max_quantity }.keys
end

p most_common('a short list of words with some words') #['words']
p most_common('Words in a short, short words, lists of words!') #['words']
p most_common('a short list of words with some short words in it') #['words', 'short']