11

products販売品と非販売品の両方を含むギャラリーを表示したいと考えています。products売り物はリストの先頭に、非売品はリストの最後に表示したいだけです。

これを達成する簡単な方法は、2 つのリストを作成し、それらをマージすることです (1 つのリストは on_sale? オブジェクトで、もう 1 つのリストは not on_sale? オブジェクトです)。

available_products = []
sold_products = []
@products.each do |product|
  if product.on_sale?
    available_products << product
  else
    sold_products << product
  end
end

. . . ただし、既存のアプリの構造を変更すると、コードが奇妙であるために過度の量のリファクタリングが必要になります (ページネーションが失われ、リファクタリングしたくありません)。ブール値を返す私のproductモデルのメソッドでオブジェクトの既存のリストをソートする方法があれば、より簡単になります。on_sale?

既存のリストをよりエレガントに反復し、レールでこの真または偽の値でソートすることは可能ですか? このフレームワーク/言語 (ruby) 内に隠されていることに気づいていないことがたくさんあり、それらが私の前に機能したかどうかを知りたいので、私は尋ねるだけです。

4

4 に答える 4

19

もちろん。理想的には、以下を使用して次のようなことを行いますsort_by!

@products.sort_by! {|product| product.on_sale?}

またはおしゃれ

@products.sort_by!(&:on_sale?)

しかし悲しいことに、<=>ブール値に対しては機能しません (Ruby のブール値でソートまたは宇宙船 (空飛ぶ円盤) 演算子 (<=>) が機能しないのはなぜですか?を参照) およびsort_byブール値に対しては機能しないため、使用する必要がありますこのトリック (rohit89 に感謝!)

@products.sort_by! {|product| product.on_sale? ? 0 : 1}

もっと手の込んだものにしたい場合は、sortメソッドがブロックを受け取り、そのブロック内で、型変換や複数のキーなど、好きなロジックを使用できます。次のようなことを試してください:

@products.sort! do |a,b|
  a_value = a.on_sale? ? 0 : 1
  b_value = b.on_sale? ? 0 : 1
  a_value <=> b_value
end

またはこれ:

@products.sort! do |a,b|
  b.on_sale?.to_s <=> a.on_sale?.to_s
end

"true"(値を前に置きたいので、bをaの前に置きます"false"

または二次ソートがある場合:

@products.sort! do |a,b|
  if a.on_sale? != b.on_sale?
    b.on_sale?.to_s <=> a.on_sale?.to_s
  else
    a.name <=> b.name
  end
end

新しいコレクションを返すことに注意してくださいsort。これは通常、よりクリーンでエラーが発生しにくいソリューションsort!ですが、要件であると述べた元のコレクションの内容を変更します。

于 2013-02-11T15:17:08.053 に答える
5

@products.sort_by {|product| product.on_sale? ? 0 : 1}

これは、ブール値に基づいてソートする必要があったときに行ったことです。

于 2013-02-11T15:30:00.997 に答える
5

並べ替える必要はありません:

products_grouped = @products.partition(&:on_sale?).flatten(1)
于 2013-02-11T15:31:38.540 に答える
0

昇順と降順は「false」と「true」を入れ替えることで可能

Products.sort_by {|product| product.on_sale? ==  true ? "false" : "true" }
于 2016-07-27T07:20:38.663 に答える