簡體   English   中英

按鍵數組中的順序對Ruby Hash進行排序

[英]Sort Ruby Hash by order in array of keys

我有一個哈希:

sample = { bar: 200, foo: 100, baz: 100 }

如何使用sort_order的鍵順序對sample進行排序:

sort_order = [:foo, :bar, :baz, :qux, :quux]

預期結果:

sample #=> { foo: 100, bar: 200, baz: 100 }

我能想出的就是

new_hash = {}
sort_order.each{|k| new_hash[k] = sample[k] unless sample[k].nil? }
sample = new_hash

必須有一個更好的方法。 提示?

不應存在​​沒有值的鍵,即鍵的數量保持不變,而排序哈希鍵的情況則不是基於數組中相同鍵的順序

使用鍵交叉的功能方法:

new_sample = (sort_order & sample.keys).map { |k| [k, sample[k]] }.to_h
#=> {:foo=>100, :bar=>200, :baz=>100}

正如@Stefan指出的那樣,來自ActiveSupport的抽象Hash#slice幾乎完成了這項任務:

require 'active_support/core_ext/hash'
new_sample = sample.slice(*sort_order)
#=> {:foo=>100, :bar=>200, :baz=>100}

下面的代碼執行此操作。 請注意我使用has_key? 因為您希望輸出哈希包含輸入哈希中的所有鍵,即使它們的值為nil

#!/usr/bin/env ruby

def sorted_hash(input_hash, key_sort_order)
  new_hash = {}
  key_sort_order.each do |key|
    if input_hash.has_key?(key)
      new_hash[key] = input_hash[key]
    end
  end
  new_hash
end

sort_order = [:foo, :bar, :baz, :qux, :quux]
sample = { bar: 200, foo: 100, baz: 100 }

puts sorted_hash(sample, sort_order)
# Outputs: {:foo=>100, :bar=>200, :baz=>100}

簡化是使用each_with_object

def sorted_hash_two(input_hash, key_sort_order)
  key_sort_order.each_with_object({}) do |key, result_hash|
    if input_hash.has_key?(key)
      result_hash[key] = input_hash[key]
    end
  end
end

puts sorted_hash_two(sample, sort_order)
# Outputs: {:foo=>100, :bar=>200, :baz=>100}

我更喜歡@ tokland關於數組交集( & )的想法,因為它消除了對if條件的需求:

def sorted_hash_ewo_intersection(input_hash, key_sort_order)
  (key_sort_order & input_hash.keys).each_with_object({}) do |key, result_hash|
    result_hash[key] = input_hash[key]
  end
end # produces: {:foo=>100, :bar=>200, :baz=>100}

請看我的答案

sort_order = [:foo, :bar, :baz, :qux, :quux, :corge, :grault,
              :garply, :waldo, :fred, :plugh, :xyzzy, :thud]
sample = { bar: 200, foo: 100, baz: 100 }

sample.sort_by {|k, _| sort_order.index(k)}.to_h
=> {:foo=>100, :bar=>200, :baz=>100}

以下是另一種方法:

(sort_order & sample.keys).zip([nil]).to_h.merge(sample)
#=> {:foo=>100, :bar=>200, :baz=>100}

說明:

首先,我們創建一個哈希,它只包含正確順序的所需鍵。

(sort_order & sample.keys).zip([nil]).to_h
#=> {:foo=>nil, :bar=>nil, :baz=>nil}

然后,我們將此哈希與sample合並以從sample獲取值。

暫無
暫無

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

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