簡體   English   中英

Ruby - 按數組順序對 hash 進行排序

[英]Ruby - Sort a hash by order of an array

我有一個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"}
]

需要 output

[
  {"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"}
]

感謝任何幫助,並提前致謝!

Map 通過您的 ID 數組到 Select 按順序匹配哈希

雖然可能有更優雅的方法來做到這一點,但我認為下面的解決方案非常清楚。 它使用您的id元素數組作為 Enumerable object 到 map,返回匹配的 Hash object 以及迭代期間遇到的每個"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"}]                                                                                         

請注意,它不會為 ID 67返回 Hash 個對象,因為它們不存在於要搜索的 ID 數組中。 您可以調整 #map 以將它們視為傳遞(盡管您沒有解釋它們應該如何或為什么出現在結果數組的末尾)或將它們添加到要搜索的元素數組中,這將是首選方法。 但是,由於它們沒有在您的原始帖子中解決,如果沒有找到匹配的 ID,這實際上是正確的 output。

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

請參閱Enumerable#sort_by 該方法使用Array#<=>對元素進行排序。 請特別參閱文檔中的第三段<=>

下面我列出了sort_byarr的每個元素使用的 arrays。

{"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 = 1x是元素的索引,它使它們在最后保持有序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM