使用Ruby中的条件逻辑对Hash进行散列?

时间:2014-05-31 22:41:55

标签: ruby-on-rails ruby ruby-2.1

ruby 2.1.1

有没有办法以一行或更简洁的方式在这段代码中执行逻辑?

user = User.new
h = Hash.new
attrs = [:name, :foo, :bar]
attrs.each do |a|
    h[a] = user[a] if user.has_attribute? a
end
return h

3 个答案:

答案 0 :(得分:3)

如果你正在使用Rails,而User是一个ActiveRecord模型(看起来好像你使用了has_attribute?),那么这将做同样的事情:

user = User.new
...
return user.attributes.slice("name", "foo", "bar")

或者,如果你真的想要符号:

return user.attributes.with_indifferent_access.slice(:name, :foo, :bar)

答案 1 :(得分:1)

好像你在使用Rails。如果是,那么 -

attrs = [:name, :foo, :bar]
# the result hash will be returned, if last line of the method.
user.attributes.extract!(*attrs) 

查看这些方法extract!attributes

示例:

arup@linux-wzza:~/Rails/app> rails c
Loading development environment (Rails 4.1.1)
2.0.0-p451 :001 > h = { a: 1, b: 2, c: 3, d: 4 }
 => {:a=>1, :b=>2, :c=>3, :d=>4}
2.0.0-p451 :002 > h.extract!(:a ,:b ,:x)
 => {:a=>1, :b=>2}
2.0.0-p451 :003 >

答案 2 :(得分:0)

上面的答案在Rails范围内是正确的,我只是添加通用解决方案:

# assuming user[a] returns nil, if user have no a attribute
[:name, :foo, :bar].
  map{|a| [attr, user[a]]}.
  reject{|k, v| v.nil?}.
  to_h

# assuming user[a] can raise if not user.has_attribute?(a)
[:name, :foo, :bar].
   map{|a| [attr, user.has_attribute?(a) && user[a]]}.
   reject{|k, v| !v}.
   to_h

我把它们格式化为非单行,但它们仍然是一个语句:)

基本上,诀窍是“发明正确的方法链将一个序列转换为另一个序列”,并且需要知道所有可枚举的序列转换方法(map / select / reduce / reject / ...),以及将键值对数组转换为哈希值的方法(#to_h是Ruby 2.1.1中的标准)