我写了一个方法,根据条件(特定的哈希值)将哈希分成两个哈希值。我的问题与another question on Hash不同。这是我期望的一个例子:
h={
:a => "FOO",
:b => "FOO",
:c => "BAR",
:d => "BAR",
:e => "FOO"
}
h_foo, h_bar = partition(h)
我需要h_foo
和h_bar
:
h_foo={
:a => "FOO",
:b => "FOO",
:e => "FOO"
}
h_bar={
:c => "BAR",
:d => "BAR"
}
我的解决方案是:
def partition h
h.group_by{|k,v| v=="FOO"}.values.collect{|ary| Hash[*ary.flatten]}
end
有一个聪明的解决方案吗?
答案 0 :(得分:5)
h.partition { |k, v| v == "FOO" }.map(&:to_h)
#=> [{:a=>"FOO", :b=>"FOO", :e=>"FOO"}, {:c=>"BAR", :d=>"BAR"}]
或者您可以使用Enumerable#each_with_object
来避免中间数组:
h.each_with_object([{}, {}]) { |(k, v), (h_foo, h_bar)|
v == "FOO" ? h_foo[k] = v : h_bar[k] = v
}
#=> [{:a=>"FOO", :b=>"FOO", :e=>"FOO"}, {:c=>"BAR", :d=>"BAR"}]
答案 1 :(得分:0)
为什么不使用内置partition
,这几乎完全符合您的要求?
h_foo, h_bar = h.partition { |key, value| value == 'FOO' }
唯一的缺点是你将获得数组而不是哈希(但你已经知道如何转换它)。在ruby 2.1+中,您只需在调用链的末尾调用.map(&:to_h)
即可。
答案 2 :(得分:-1)
我不认为有一个聪明的单行,但你可以通过做类似的事情使它更通用:
def transpose(h,k,v)
h[v] ||= []
h[v] << k
end
def partition(h)
n = {}
h.map{|k,v| transpose(n,k,v)}
result = n.map{|k,v| Hash[v.map{|e| [e, k]}] }
end
将产生
[{:a=>"FOO", :b=>"FOO", :e=>"FOO"}, {:c=>"BAR", :d=>"BAR"}]
针对您的初始哈希h
编辑 - 关于partition
的TIL。恶