我的哈希看起来像这样:
{ "3g3dsd3" => {"price"=>0.12, "avg"=>81, "top"=>true}, "1sf3af" => {"price"=>0.14, "avg"=>121, "top"=>false}...}
我想对其重新排序,以使带有"top"=>true
的项位于最前面,但是除此之外,这些项将保持先前的顺序,这意味着具有相同top
值的项将不会在两个时间之间更改顺序。 / p>
我在原始文档中找不到证据sort_by
保留未排序属性的顺序。
我该怎么做?
答案 0 :(得分:2)
您可以通过合并sort_by
使with_index
稳定。
代替:
collection.sort_by { |...| ... }
您写:
collection.sort_by.with_index { |(...), i| [..., i] }
适用于您的问题:
hash.sort_by { |_k, v| v['top'] ? 0 : 1 } # unstable
hash.sort_by.with_index { |(_k, v), i| [v['top'] ? 0 : 1, i] } # stable
答案 1 :(得分:1)
sort_by
特别声明:
不能保证结果稳定。当两个键相等时,相应元素的顺序是不可预测的。
意味着您的问题是有根据的。
在这种情况下,您可以使用partition
将集合分成两个部分。然后按照您想要的方式将它们粘贴回去。
top, non_top = hash.partition { |key, hash| hash['top'] }
result = (top + non_top).to_h
partition
保持原始数组的顺序。
如果您是一个班轮的粉丝,那么在这种情况下,以下操作也一样。
result = hash.partition { |key, hash| hash['top'] }.flatten(1).to_h
答案 2 :(得分:0)
Ruby sort / sort_by
不稳定。但是,您可以将原始输入中的索引用作抢七游戏:Is sort in Ruby stable?
答案 3 :(得分:0)
这是一种对哈希的键值对重新排序的方法,无需将哈希转换为一个或多个数组,然后在修改后将这些数组转换回哈希。
假设
h = { "2rh4abc" => {"price"=>0.18, "avg"=>130, "top"=>false },
"3g3dsd3" => {"price"=>0.12, "avg"=>81, "top"=>true },
"1sf3af" => {"price"=>0.14, "avg"=>121, "top"=>false } }
然后
top_key = h.find { |_,v| v["top"] == true }.first
#=> "3g3dsd3"
{ top_key=>h[top_key] }.merge(h.reject { |k,_| k == top_key })
#=> {"3g3dsd3"=>{"price"=>0.12, "avg"=>81, "top"=>true},
# "2rh4abc"=>{"price"=>0.18, "avg"=>130, "top"=>false},
# "1sf3af"=>{"price"=>0.14, "avg"=>121, "top"=>false}}
如果可以对h
进行突变(就地修改),则可以简化为:
{ top_key=>h.delete(top_key) }.merge(h)
#=> {"3g3dsd3"=>{"price"=>0.12, "avg"=>81, "top"=>true},
# "2rh4abc"=>{"price"=>0.18, "avg"=>130, "top"=>false},
# "1sf3af"=>{"price"=>0.14, "avg"=>121, "top"=>false}}