选择并从ruby中的哈希中删除

时间:2013-06-22 11:46:39

标签: ruby

在一个方法中,我得到一个传入的选项列表。一些与特定范围有关。 我想将这些特殊键存储在另一个哈希中,以便能够将它传递给另一个方法,并从原始哈希中删除它们。

(我实际上是在编写一个rails simple_form自定义输入,但这没关系)

我有以下代码:

all_options = { :key1 => 1, :key2 => 2, :something_else => 42 }

my_keys = [:key1, :key2, :key3, :key4]
my_options = all_options.select {|k,v| my_keys.include?(k)}
all_options.delete_if {|k,v| my_keys.include?(k)}

# expecting
my_options == { :key1 => 1, :key2 => 2 }
all_options == { :something_else => 42 }

现在我的问题是有更好的,更明智的做法吗?

也许这只是糖,但我想知道。

4 个答案:

答案 0 :(得分:1)

也许active_support中的extract!方法可以正常工作?

答案 1 :(得分:1)

我只知道Ruby。所以这里我的Ruby方法:

all_options = { :key1 => 1, :key2 => 2, :something_else => 42 }

my_keys = [:key1, :key2, :key3, :key4]

#below statement is your my_options

Hash[my_keys.map{|i| [i,all_options.delete(i)] if all_options.has_key? i }.compact]
# => {:key1=>1, :key2=>2}

all_options
# => {:something_else=>42}

答案 2 :(得分:1)

all_options = { :key1 => 1, :key2 => 2, :something_else => 42 }
my_keys = [:key1, :key2, :key3, :key4]

my_options = my_keys.inject({}) {|h,k| h[k] = all_options.delete(k) if all_options.key?(k);h}

all_options
# => {:something_else=>42}
my_options
# => {:key1=>1, :key2=>2}

这是改善Ju Liu答案的一种方法:

all_options = { :key1 => 1, :key2 => 2, :something_else => 42 }
my_keys = [:key1, :key2, :key3, :key4]

my_options = all_options.extract!(*my_keys).keep_if {|k,v| v}

all_options
# => {:something_else=>42}
my_options
# => {:key1=>1, :key2=>2}

但是,如果all_options哈希中的任何键的实际值为nilfalse(不知道是否需要保留它们),您将失去选项:

all_options = { :key1 => 1, :key2 => nil, :something_else => 42 }

这是保留false

的方法
my_options = all_options.extract!(*my_keys).keep_if {|k,v| !v.nil?}

P.S。如果您存储来自nil的密钥,则可以保留所有值,包括all_options

all_options = { :key1 => 1, :key2 => 2, :something_else => 42 }
all_keys = all_options.keys
my_keys = [:key1, :key2, :key3, :key4]

my_options = all_options.extract!(*my_keys).keep_if {|k,v| all_keys.include?(k)}

all_options
# => {:something_else=>42}
my_options
# => {:key1=>1, :key2=>2}

答案 3 :(得分:0)

all_options = { key1: 1, key2: 2, something_else: 42 }
my_keys = [:key1, :key2, :key3, :key4]

my_options = my_keys.each_with_object({}) do |key, hash|
  hash[key] = all_options.delete(key) if all_options.key?(key)
end