如何用多个条件对字符串数组进行排序?

时间:2014-07-31 11:30:25

标签: ruby-on-rails ruby arrays sorting

我有一个字符串数组,需要按多个条件(两个字符串属性)排序。但是,这两种排序需要按相反的方向排序。

示例:

  

数组必须按属性_a以desc顺序排序,然后在其中   按asc顺序按attribute_b排序。

我一直在使用.sort_by!哪个工作正常,但我只是不确定如何在相反的排序方向上实现两个标准排序

4 个答案:

答案 0 :(得分:4)

如果这些属性是数据库列,则可以使用:

Organization.order(attribute_a: :desc, attribute_b: :asc)

否则,请将sortarray

一起使用
  

阵列以“元素方式”进行比较;前两个不相等的元素将决定整个比较的返回值。

交换第一个元素按降序对它们进行排序:

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">]