2011-01-25 24 views
1

単語がアルファベット順に表示された回数に基づいてドキュメントをソートしようとしています。Rubyでハッシュ値を最初にソートしてからキーを

Unsorted: 
'the', '6' 
'we', '7' 
'those', '5' 
'have', '3' 

Sorted: 
'we', '7' 
'the', '6' 
'those', '5' 
'have', '3' 
+0

ソートされていないリストに何かを追加して、アルファベット順にソートしているかどうかを確認することをお勧めします。私は 'と=> 6 'を追加しました。つまり、'、 '6の前に'と '6'があるはずです。 – Mikel

+0

あなたの問題をもっときれいに解決するために私の答えを更新しました:)。見てみな。 –

答えて

10

これを試してみてください:

と仮定:

a = { 
    'the' => '6', 
    'we' => '7', 
    'those' => '5', 
    'have' => '3', 
    'hav' => '3', 
    'haven' => '3' 
} 

その後、これを実行した後:

b = a.sort_by { |x, y| [ -Integer(y), x ] } 

bは次のようになります。

[ 
    ["we", "7"], 
    ["the", "6"], 
    ["those", "5"], 
    ["hav", "3"], 
    ["have", "3"], 
    ["haven", "3"] 
] 

逆周波数でソートするように編集されています。

+0

この投稿はかなり古いです。 IDは試してみた。 yを整数に変更していない場合、-Integer(y)の部分は何をしていますか? –

+1

@ZachSmithこれは、数字を負にしているので、ソート順を最小から最小に最大から最小に逆順にします。 –

3
words = {'the' => 6,'we' => 7,'those' => 5,'have' => 3} 
sorted_words = words.sort { |a,b| b.last <=> a.last } 
sorted_words.each { |k,v| puts "#{k} #{v}"} 

生成:

we 7 
the 6 
those 5 
have 3 

をあなたはおそらく値が整数ではなく、比較のために文字列になりたいです。

EDIT

おっと、それはあまりにもキーでソートする必要要件を見落とし。だから、:

words = {'the' => 6,'we' => 7,'those' => 5,'have' => 3,'zoo' => 3,'foo' => 3} 
sorted_words = words.sort do |a,b| 
    a.last == b.last ? a.first <=> b.first : b.last <=> a.last 
end 
sorted_words.each { |k,v| puts "#{k} #{v}"} 

は生成します。

we 7 
the 6 
those 5 
foo 3 
have 3 
zoo 3 
0
word_counts = { 
     'the' => 6, 
     'we' => 7, 
     'those' => 5, 
     'have' => 3, 
     'and' => 6 
}; 

word_counts_sorted = word_counts.sort do 
     |a,b| 
     # sort on last field descending, then first field ascending if necessary 
     b.last <=> a.last || a.first <=> b.first 
end 

puts "Unsorted\n" 
word_counts.each do 
     |word,count| 
     puts word + " " + count.to_s 
end 

puts "\n" 
puts "Sorted\n" 
word_counts_sorted.each do 
     |word,count| 
     puts word + " " + count.to_s 
end 
0

1.9.1

>> words = {'the' => 6,'we' => 7, 'those' => 5, 'have' => 3} 
=> {"the"=>6, "we"=>7, "those"=>5, "have"=>3}    
>> words.sort_by{ |x| x.last }.reverse 
=> [["we", 7], ["the", 6], ["those", 5], ["have", 3]] 
+0

再び、私はこれがハッシュキーのアルファベット順に等しい数値のソートであるとは思わない。 – Mikel

+0

はい、これは私が見逃していた2番目の基準をソートしません。 – kurumi

1

を使用すると、ハッシュにsortメソッドを使用すると、あなたの比較ブロックに2つの素子アレイを受け取りますあなたは1回のパスで比較を行うことができます。

words = {'the' => 6,'we' => 7,'those' => 5,'have' => 3} 

words.sort { |(x_k, x_v), (y_k, y_v)| [y_v, y_k] <=> [x_v, x_k]} 
#=> [["we", 7], ["the", 6], ["those", 5], ["have", 3]] 
+0

ありがとうございます。私は 'Hash#sort'文書のためにhttp://ruby-doc.org/core/classes/Hash.html#M000743を見ていましたが、それらはかなり不十分です。良い方法があるはずだと分かっていた。 – Mikel

+0

実際、[Enumerableモジュールのソート方法](http://ruby-doc.org/core/classes/Enumerable.html#M001480)をチェックしてください。これがHashのソート機能です。 – edgerunner

+0

ええ、私はそれを考え出しました。私がすぐに気付かなかったのは、配列の配列を返すということでした。私は 'ハッシュ#each 'が効果的にペアを返すと思うので、そういうものを考えていたはずです。 – Mikel

1

これを試してみて、配列の配列であることを

hsh = { 'the' => '6', 'we' => '6', 'those' => '5', 'have' => '3'} 
ary = hsh.sort do |a,b| 
    # a and b are two element arrays in the format [key,value] 
    value_comparison = a.last <=> b.last 
    if value_comparison.zero? 
    # compare keys if values are equal 
    a.first <=> b.first 
    else 
    value_comparison 
    end 
end 
# => [['have',3],['those',5],['the',6],['we',6]] 

注意数字を保存する。データモデルでは、文字列を使用して数値を格納するように見えます。なぜあなたがこれをやりたいのか分からないが、の場合はがこれをやりたければ、ソートする前に数値に変換してから文字列に戻す必要があります。

また、これはRuby 1.9を前提としています。 Ruby 1.8では、ハッシュは順序付けされていないので、ソートされた結果をハッシュに変換することはできません。順序情報を失うため、配列として保持する必要があります。

1
histogram = { 'the' => 6, 'we' => 7, 'those' => 5, 'have' => 3, 'and' => 6 } 

Hash[histogram.sort_by {|word, freq| [-freq, word] }] 
# { 
# 'we' => 7, 
# 'and' => 6, 
# 'the' => 6, 
# 'those' => 5, 
# 'have' => 3 
# } 

注:これはあなたが番号を使用することを前提としていた結果がハッシュはルビーに固有の順序を持​​っていないので、

関連する問題