Ruby -按数组的顺序排序哈希



我有一个array和一个hash,我想要实现的是根据数组中的排序对hash(每个散列内的id)进行排序,如果id(在hash中)不存在于my_array中,它们不应该被删除,只是在排序中被推下。

my_array = [4, 2, 5, 3, 1]
hash = [
{"id" => 1, "field_name" => "foo"},
{"id" => 2, "field_name" => "bar"},
{"id" => 3, "field_name" => "abc"},
{"id" => 4, "field_name" => "zsh"},
{"id" => 5, "field_name" => "kql"},
{"id" => 6, "field_name" => "plo"},
{"id" => 7, "field_name" => "cde"}
]

需要输出

[
{"id" => 4, "field_name" => "zsh"},
{"id" => 2, "field_name" => "bar"},
{"id" => 5, "field_name" => "kql"},
{"id" => 3, "field_name" => "abc"},
{"id" => 1, "field_name" => "foo"},
{"id" => 6, "field_name" => "plo"},
{"id" => 7, "field_name" => "cde"}
]

感谢任何帮助和提前感谢!

my_array = [4, 7, 5, 3, 1]
arr = [
{"id" => 1, "field_name" => "foo"},
{"id" => 2, "field_name" => "bar"},
{"id" => 3, "field_name" => "abc"},
{"id" => 4, "field_name" => "zsh"},
{"id" => 5, "field_name" => "kql"},
{"id" => 6, "field_name" => "plo"},
{"id" => 7, "field_name" => "cde"}
]

请注意,我已经改变了my_array从问题中给出的,并已将数组重命名为更合适的东西。

arr.sort_by.with_index do |h,i|
my_array.include?(h["id"]) ? [0, h["id"]] : [1,i]
end
#=> [{"id"=>1, "field_name"=>"foo"},
#    {"id"=>3, "field_name"=>"abc"},
#    {"id"=>4, "field_name"=>"zsh"},
#    {"id"=>5, "field_name"=>"kql"},
#    {"id"=>7, "field_name"=>"cde"},
#    {"id"=>2, "field_name"=>"bar"},
#    {"id"=>6, "field_name"=>"plo"}]

看到可列举的# sort_by。该方法使用Array#<=>排序元素。参见文档中<=>的第三段。

下面我列出了sort_byarr的每个元素所使用的数组。

{"id" => 1, "field_name" => "foo"}  ->  [0, 1]
{"id" => 2, "field_name" => "bar"}  ->  [1, 1]
{"id" => 3, "field_name" => "abc"}  ->  [0, 3]   
{"id" => 4, "field_name" => "zsh"}  ->  [0, 4]
{"id" => 5, "field_name" => "kql"}  ->  [0, 5]
{"id" => 6, "field_name" => "plo"}  ->  [1, 5]
{"id" => 7, "field_name" => "cde"}  ->  [0, 7]

如果[type, x]sort_by用来排序的数组,它将把type 0对应的所有元素放在type = 1对应的元素之前。为了打破束缚,它按x排序元素。对于type = 1,x是元素的索引,使它们在末尾保持顺序。

映射ID数组,按顺序选择匹配的哈希

虽然可能有更优雅的方法来做到这一点,我认为下面的解决方案是相当清楚的。它使用id元素的数组作为可枚举对象进行映射,为迭代期间遇到的每个"id"键返回具有匹配值的匹配哈希对象(如果找到),然后删除未找到匹配的任何元素,例如#map返回的数组返回nil

使用Ruby 3.1.2:

id_order = [4, 2, 5, 3, 1]
array_of_hashes = [
{"id" => 1, "field_name" => "foo"},
{"id" => 2, "field_name" => "bar"},
{"id" => 3, "field_name" => "abc"},
{"id" => 4, "field_name" => "zsh"},
{"id" => 5, "field_name" => "kql"},
{"id" => 6, "field_name" => "plo"},
{"id" => 7, "field_name" => "cde"}
]
id_order.map { |id| array_of_hashes.detect { |h| h["id"] == id } }.compact

这将正确返回第一个数组中指定的有序结果:

#=> 
[{"id"=>4, "field_name"=>"zsh"},                                                                                         
{"id"=>2, "field_name"=>"bar"},                                                                                         
{"id"=>5, "field_name"=>"kql"},                                                                                         
{"id"=>3, "field_name"=>"abc"},                                                                                         
{"id"=>1, "field_name"=>"foo"}]                                                                                         

请注意,它不会返回id67的哈希对象,因为它们不存在于您要搜索的id数组中。您可以调整#map以将它们视为传递(尽管您还没有解释它们应该如何或为什么出现在结果数组的末尾),或者将它们添加到要搜索的元素数组中,这将是首选的方法。但是,由于它们没有在您的原始帖子中解决,如果没有找到匹配的ID,这实际上是正确的输出。

相关内容

  • 没有找到相关文章

最新更新