1

私はハッシュの配列を持っています:

a = [
  { :id => 10, :name => 'bush' },
  { :id => 2, :name => 'sugar' },
  { :id => 10, :name => 'mountain' },
  { :id => 10, :name => 'bug' },
  { :id => 8, :name => 'sugar' }
]

最初にIDの昇順で配列をソートし、次に名前のアルファベット順で降順でソートしたいので、最終結果は次のようになります。

a = [
  { :id => 2, :name => 'sugar' },
  { :id => 8, :name => 'sugar' },
  { :id => 10, :name => 'mountain' },
  { :id => 10, :name => 'bush' },
  { :id => 10, :name => 'bug' }
]

どうすればこれを達成できますか?

4

5 に答える 5

4

質問に加えられた編集に基づいて、使用する従来の並べ替えを行うには

a.sort { |a, b| [a[:id], a[:name]] <=> [b[:id], b[:name]] }
=> [
  {:id=>2, :name=>"sugar"},
  {:id=>8, :name=>"sugar"},
  {:id=>10, :name=>"bug"},
  {:id=>10, :name=>"bush"},
  {:id=>10, :name=>"mountain"}
]  

条件チェックを入れ替えることでソート順を切り替えることができます。

a.sort { |a, b| [a[:id], b[:name]] <=> [b[:id], a[:name]] }
=> [
  {:id=>2, :name=>"sugar"},
  {:id=>8, :name=>"sugar"},
  {:id=>10, :name=>"mountain"},
  {:id=>10, :name=>"bush"},
  {:id=>10, :name=>"bug"}
]
于 2013-03-15T16:13:21.537 に答える
1

a.sort {| a、b | (a [:id]!= b [:id])?a [:id] <=> b [:id]:b [:name] <=> a [:name]}

>> a
=> [{:id=>10, :name=>"bush"}, {:id=>2, :name=>"sugar"}, {:id=>10, :name=>"mountain"}, {:id=>10, :name=>"bug"}, {:id=>8, :name=>"sugar"}]
>> a.sort {|a,b| (a[:id] != b[:id]) ? a[:id] <=> b[:id] : b[:name] <=> a[:name] }
=> [{:id=>2, :name=>"sugar"}, {:id=>8, :name=>"sugar"}, {:id=>10, :name=>"mountain"}, {:id=>10, :name=>"bush"}, {:id=>10, :name=>"bug"}]
>>
于 2013-03-15T16:11:42.987 に答える
1

楽しみのために、何年も前からあるパターンを次に示します。

class SortByInverter < Struct.new(:value)
  def <=>(other)
    other.value <=> value
  end
end

class Object
  def desc
    SortByInverter.new(self)
  end
end

そして今それを使用しましょう:

hs.sort_by { |h| [h[:id], h[:name].desc] }

もちろん、コンテナ クラスを直接使用することもできます (より冗長ですが、恐ろしい拡張機能はありませんObject)。

hs.sort_by { |h| [h[:id], SortByInverter.new(h[:name])] }
于 2013-03-15T19:55:54.847 に答える
1

@DanReedyの答えは明確にするために優れていると思いますが、小さな中間配列をたくさん作成し、ハッシュルックアップを繰り返すため、大きなリストに適用するとパフォーマンスの問題が発生する可能性があります sort_by。 O(N logN) 個の比較で再利用されるキーを O(N) 回並べ替える 2 次キーの降順を実現するには、比較方法の順序を逆にする方法が必要です。

module DescendingComparable
  def <=>(other)
    - super
  end
end

pry(main)> a.sort_by {|e| [ e[:id], e[:name].dup.extend(DescendingComparable) ] }
=> [{:id=>2, :name=>"sugar"},
 {:id=>8, :name=>"sugar"},
 {:id=>10, :name=>"mountain"},
 {:id=>10, :name=>"bush"},
 {:id=>10, :name=>"bug"}]
于 2013-03-15T19:09:09.947 に答える
0

あなたはそのようなことを試すことができます

a.sort do |a1, a2|
  comparison = a1[:id] <=> a2[:id]
  (comparison != 0) ? comparison : a1[:name] <=> a2[:name]
end
于 2013-03-15T16:12:21.520 に答える