我正在使用Ruby 1.8.7。我有以下哈希数组。我需要先按布尔值排序,但这些结果必须按原始顺序排序。我基本上需要将所有真正的哈希值移到数组顶部,但保持原始顺序。
任何帮助将不胜感激!
array = [{:id => 1, :accepts => false},
{:id => 2, :accepts => false},
{:id => 3, :accepts => true},
{:id => 4, :accepts => false},
{:id => 5, :accepts => true}]
sorted = array.sort do |x, y|
if x[:accepts] == y[:accepts]
0
elsif x[:accepts] == true
-1
elsif x[:accepts] == false
1
end
end
这种我得到的结果:
5 - 真实
3 - 真实
2 - 假
4 - 假
1 - 假
我需要它来产生:
3 - 真实
5 - 真实
1 - 假
2 - 假
4 - 假
答案 0 :(得分:14)
使用sort_by
来做这些事情,而不是sort
!
array.sort_by {|h| [h[:accepts] ? 0 : 1,h[:id]]}
答案 1 :(得分:8)
这就是工作:
array.sort{|a,b| (a[:accepts] == b[:accepts]) ? ((a[:id] < b[:id]) ? -1 : 1) : (a[:accepts] ? -1 : 1)}
答案 2 :(得分:1)
答案 3 :(得分:1)
好吧,根据您的问题,我推断您确实希望按:accepts
值对结果进行分组,并将两个结果集合并回一个数组。我的解决办法就是:
array.select {|where| where[:accepts] } | array.reject {|where| where[:accepts] }
# => [{:accepts=>true, :id=>3},
# {:accepts=>true, :id=>5},
# {:accepts=>false, :id=>1},
# {:accepts=>false, :id=>2},
# {:accepts=>false, :id=>4}]
这将维持原始订单,而不会在:id
键上隐含任何排序。这意味着您不需要辅助键来保留顺序,并且无论传输的数据如何,您都可以保留结果的顺序。
这可能也很有用(也许正是您进一步评估所需要的):
array.group_by {|where| where[:accepts] }
# => {false=>[{:accepts=>false, :id=>1},
# {:accepts=>false, :id=>2},
# {:accepts=>false, :id=>4}],
# true=>[{:accepts=>true, :id=>3},
# {:accepts=>true, :id=>5}]}
同样,没有人工排序...... group_by
是1.8.7中的新内容。
PS:如果您不希望第一个代码段从阵列中删除重复项,请使用plus运算符替换bar运算符。 “|”根据{{3}}(union)合并两个集合,而“+”连接两个集合(结果实际上不是集合而是普通数组)。
答案 4 :(得分:0)
如果:id
相等,您可以在:accepts
键上添加额外的检查,如下所示:
array = [{:id => 1, :accepts => false},
{:id => 2, :accepts => false},
{:id => 3, :accepts => true},
{:id => 4, :accepts => false},
{:id => 5, :accepts => true}]
sorted = array.sort do |x, y|
if x[:accepts] == y[:accepts]
if x[:id] == y[:id]
0
elsif x[:id] > y[:id]
1
elsif x[:id] < y[:id]
-1
end
elsif x[:accepts] == true
-1
elsif x[:accepts] == false
1
end
end
答案 5 :(得分:0)
a.sort_by { |x| (x[:accepts] ? 0 : 99999) + x[:id] }
更新:显然,这需要x[:id].respond_to? "+"
,并且相对于常量,其范围也有限制。
然而,这是最短且可能是最快的答案,如果也显然是最值得怀疑的。
真正重要的一课是,它说明一个人应该超越Array
(或其他),并检查Enumerable
是否在(your object).class.ancestors
。这些问题和他们的观众经常回答“我接下来应该学习什么关于Ruby,我怀疑还有其他方法”。
无论这是一种好的排序方式(不可否认,这是有问题的),这个答案建议#sort_by
,只是找到#sort_by
的文档(它不在数组中)将为初学者教授一个小而重要的课程。
答案 6 :(得分:0)
这是因为Ruby 1.8.7中的排序不稳定
您需要做的就是让排序块不返回0
:
sorted = array.sort do |x, y|
if x[:accepts] == y[:accepts]
x[:id] <=> y[:id] # not 0
elsif x[:accepts]
-1
else
1
end
end
(无需明确将布尔值与true
和false
)