Как извлечь дополнительный хеш из хеша? - PullRequest
83 голосов
/ 27 января 2012

У меня есть хеш:

h1 = {:a => :A, :b => :B, :c => :C, :d => :D}

Каков наилучший способ извлечения такого подхеша, как этот?

h1.extract_subhash(:b, :d, :e, :f) # => {:b => :B, :d => :D}
h1 #=> {:a => :A, :c => :C}

Ответы [ 16 ]

1 голос
/ 27 января 2012
class Hash
  def extract(*keys)
    key_index = Hash[keys.map{ |k| [k, true] }] # depends on the size of keys
    partition{ |k, v| key_index.has_key?(k) }.map{ |group| Hash[group] }  
  end
end

h1 = {:a => :A, :b => :B, :c => :C, :d => :D}
h2, h1 = h1.extract(:b, :d, :e, :f)
0 голосов
/ 05 июля 2019

Мы можем сделать это, зациклившись на ключах, которые мы хотим извлечь, и просто проверив, существует ли ключ, а затем извлеките его.

class Hash
  def extract(*keys)
    extracted_hash = {}
    keys.each{|key| extracted_hash[key] = self.delete(key) if self.has_key?(key)}
    extracted_hash
  end
end
h1 = {:a => :A, :b => :B, :c => :C, :d => :D}
h2 = h1.extract(:b, :d, :e, :f)
0 голосов
/ 05 июля 2019

Просто дополнение к методу слайса, если ключи хеша, которые вы хотите отделить от оригинального хеша, будут динамическими, вы можете сделать как,

slice(*dynamic_keys) # dynamic_keys should be an array type 
0 голосов
/ 23 мая 2019

Как уже упоминалось, в Ruby 2.5 добавлен метод среза Hash #.

Rails 5.2.0beta1 также добавил свою собственную версию Hash # slice для упрощения функциональности для пользователей платформы, которые используют более раннюю версию Ruby.https://github.com/rails/rails/commit/01ae39660243bc5f0a986e20f9c9bff312b1b5f8

Если по какой-либо причине вы хотите реализовать свой собственный вариант, это тоже хороший вариант:

 def slice(*keys)
   keys.each_with_object(Hash.new) { |k, hash| hash[k] = self[k] if has_key?(k) }
 end unless method_defined?(:slice)
0 голосов
/ 03 мая 2018

Вот функциональное решение, которое может быть полезно, если вы не работаете на Ruby 2.5 и если вы не хотите загрязнять свой класс Hash, добавив новый метод:

slice_hash = -> keys, hash { hash.select { |k, _v| keys.include?(k) } }.curry

Тогда вы можете применить его даже к вложенным хэшам:

my_hash = [{name: "Joe", age: 34}, {name: "Amy", age: 55}]
my_hash.map(&slice_hash.([:name]))
# => [{:name=>"Joe"}, {:name=>"Amy"}]
0 голосов
/ 27 января 2012

Этот код внедряет запрашиваемую функциональность в класс Hash:

class Hash
    def extract_subhash! *keys
      to_keep = self.keys.to_a - keys
      to_delete = Hash[self.select{|k,v| !to_keep.include? k}]
      self.delete_if {|k,v| !to_keep.include? k}
      to_delete
    end
end

и выдает предоставленные вами результаты:

h1 = {:a => :A, :b => :B, :c => :C, :d => :D}
p h1.extract_subhash!(:b, :d, :e, :f) # => {b => :B, :d => :D}
p h1 #=> {:a => :A, :c => :C}

Примечание: этот метод фактически возвращаетизвлеченные ключи / значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...