1

値を配列としてハッシュを作成しようとしています。これらの配列に要素を追加していますが、何らかの理由で、実行後にハッシュが空になります。理由はまったくわかりません。これが私のコードです

def function(words)
  hash = Hash.new([])  # default value of empty list
  words.each do |word|
    sorted = word.chars.sort.join  # sort the string
    hash[sorted] << word
    ## hash becomes empty here
  end
  return hash
end

puts function ['cars', 'for', 'potatoes', 'racs', 'four']

私はRubyが初めてで、ハッシュがそれ自体を空にする理由がわかりません。Python で同じロジックを持つ同様のアルゴリズムを作成しましたが、まったく問題なく動作します。助言がありますか?

4

2 に答える 2

1

問題は、指定したデフォルトのハッシュ値が変更可能な値であることです (部分的に、少なくとも — 以下を参照)。代わりにHash.newのブロック パラメータを使用する必要があります。

hash = Hash.new { |h, k| h[k] = [] }

正しい結果が得られます。

function ['cars', 'for', 'potatoes', 'racs', 'four']
#=> {"acrs"=>["cars", "racs"],
#    "for"=>["for"],
#    "aeoopstt"=>["potatoes"],
#    "foru"=>["four"]}

あなたが持っているものの問題は、それがhash[sorted]返すことですが[]、実際には割り当てられません。したがって、配列を変更しますが、ハッシュには入れないでください。代わりに使用する場合+=(を残してHash.new([])、これも機能することができます:

hash[sorted] += [words]
于 2013-01-20T06:26:11.793 に答える
-2

ハッシュキーに値を割り当てる=

hash[sorted] << word次のものに置き換えることで、コードを簡単に修正できます。

hash[sorted] = word

元のコードを機能させるために実際に必要だった変更はこれだけです。検討:

def function(words)
  hash = Hash.new([])
  words.each do |word|
    sorted = word.chars.sort.join
    hash[sorted] = word
  end
  return hash
end

戻り値:

function %w[cars for potatoes racs four]
# => {"acrs"=>"racs", "for"=>"for", "aeoopstt"=>"potatoes", "foru"=>"four"}

ほぼ予想通り。投稿された例では、wordは配列ではなく文字列です。割り当てを修正するだけでなく、ハッシュ値を配列としてキャストしたい場合は、以下の推奨されるリファクタリングを参照してください。

コードのリファクタリング

これを元の方法からクリーンアップする方法はいくつかあります。たとえば、コードをリファクタリングして、より慣用的で読みやすくする 1 つの方法を次に示します。

def sort_words words
  hash = {}
  words.map { |word| hash[word.chars.sort.join] = Array(word) }
  hash
end

sort_words %w[cars for potatoes racs four]
# => {"acrs"=>["racs"], "for"=>["for"], "aeoopstt"=>["potatoes"], "foru"=>["four"]}

他のリファクタリングも確かに可能です --- Ruby は非常に柔軟で表現力豊かな言語です --- しかし、これで正しい道を歩み始めることができます。

于 2013-01-20T06:21:24.453 に答える