Ruby sort_by保持未排序的原始顺序

时间:2020-11-11 17:22:23

标签: ruby

我的哈希看起来像这样:

{ "3g3dsd3" => {"price"=>0.12, "avg"=>81, "top"=>true}, "1sf3af" => {"price"=>0.14, "avg"=>121, "top"=>false}...}

我想对其重新排序,以使带有"top"=>true的项位于最前面,但是除此之外,这些项将保持先前的顺序,这意味着具有相同top值的项将不会在两个时间之间更改顺序。 / p>

我在原始文档中找不到证据sort_by保留未排序属性的顺序。

我该怎么做?

4 个答案:

答案 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}} 
相关问题