我有一个字符串数组,需要按多个条件(两个字符串属性)排序。但是,这两种排序需要按相反的方向排序。
示例:
数组必须按属性_a以desc顺序排序,然后在其中 按asc顺序按attribute_b排序。
我一直在使用.sort_by!哪个工作正常,但我只是不确定如何在相反的排序方向上实现两个标准排序
答案 0 :(得分:4)
如果这些属性是数据库列,则可以使用:
Organization.order(attribute_a: :desc, attribute_b: :asc)
一起使用
阵列以“元素方式”进行比较;前两个不相等的元素将决定整个比较的返回值。
交换第一个元素按降序对它们进行排序:
array.sort { |x, y| [y.attribute_a, x.attribute_b] <=> [x.attribute_a, y.attribute_b] }
# ^ ^
# | |
# +-------- x and y exchanged -------+
要生成your comment中提到的列表,您可以使用group_by
:
<% sorted_array.group_by(&:attribute_a).each do |attr, group| %>
<%= attr %> #=> "Type z"
<% group.each do |item| %>
<%= item.attribute_b %> #=> "name a", "name b", ...
<% end %>
<% end %>
答案 1 :(得分:1)
您可以这样做:
sorted = a.group_by(&:attribute_a).each do |k, v|
v.sort_by!(&:attribute_b)
end.sort_by(&:first).map(&:last)
sorted.reverse.flatten
此解决方案按attribute_a
对所有元素进行分组,按attribute_b
(asc)对每个组进行排序,按attribute_a
(asc)对各组进行排序。
第二行反转组的顺序(不更改组内元素的顺序),然后展平结果,导致原始列表按attribute_a
排序(desc),attribute_b
(asc)
答案 2 :(得分:0)
尝试类似的东西:
a.sort! do |x, y|
xa = get_a(x)
ya = get_a(y)
c = ya - xa
return c unless c == 0
xb = get_b(x)
yb = get_b(y)
return xb - yb
end
get_a 和 get_b 是提取 a 和 b 参数的函数
答案 3 :(得分:0)
这是使用sort的直接解决方案。通过否定&lt; =&gt;:
的结果来创建相反的顺序sorted = some_things.sort do |x,y|
if x.a == y.a
x.b <=> y.b
else
-(x.a <=> y.a) # negate to reverse the order
end
end
这是测试它的完整程序:
class Thing
attr_reader :a, :b
def initialize(a, b)
@a = a
@b = b
end
end
# Create some Things
some_things = [Thing.new("alpha","zebra"), Thing.new("gamma", "yoda"),
Thing.new("delta", "x-ray"), Thing.new("alpha", "yoda"),
Thing.new("delta", "yoda"), Thing.new("gamma", "zebra")]
sorted = some_things.sort do |x,y|
if x.a == y.a
x.b <=> y.b
else
-(x.a <=> y.a) # negate to reverse the order
end
end
p sorted
产生此输出(插入换行符):
[#<Thing:0x007fddca0949d0 @a="gamma", @b="yoda">,
#<Thing:0x007fddca0947f0 @a="gamma", @b="zebra">,
#<Thing:0x007fddca094958 @a="delta", @b="x-ray">,
#<Thing:0x007fddca094868 @a="delta", @b="yoda">,
#<Thing:0x007fddca0948e0 @a="alpha", @b="yoda">,
#<Thing:0x007fddca094a48 @a="alpha", @b="zebra">]