Ruby惯用法 - 不使用`if`语句,仅在变量不为nil时赋值

4
我有很多类似这样的行。
api_data[:foo] = foo if foo
api_data[:bar] = bar if bar
api_data[:batz] = batz if batz

我希望能够简洁、惯用的方式来进行赋值,但只在不为nil的情况下才执行。谢谢。

为什么你不想使用 if 语句? - Hamms
false 怎么办?你的代码与描述不符。 - cremno
1
api_data[:foo] = foo unless foo.nil? - Hamms
如果 foo 可以等于 false,那么你所拥有的与你想要的是不同的。对于 foo,有四种可能性:foo 等于 nilfoo 等于 falsefoo 等于除 nilfalse 之外的真值,以及 foo 未被定义。你是否想考虑这四种可能性? - Cary Swoveland
5个回答

3

如果您只想指定非 nil 的值:

api_data.merge!(
  {
    foo: foo,
    bar: bar,
    bart: barts
  }.reject { |_,v|v.nil? }
)

这有点混乱,因此您可能希望创建一个扩展到哈希(Hash)类的程序,以忽略 nil 分配:
class PickyHash < Hash
  def []=(k,v)
    return if (v.nil?)
    super
  end
end

然后:

api_data = PickyHash.new
api_data[:foo] = 'foo'
api_data[:foo] = nil

api_data
#> {:foo=>"foo"}

api_data[:foo] ||= foo 只有当 api_data[:foo] 为 false(即 nil 或 false)时才会赋值,这似乎并没有回答问题。 - floum
@harald 谢谢。已做出更新。 - tadman
按照你目前的速度,大约需要七个晚上后才能滚动零。 - Cary Swoveland

1
api_data[:foo] = foo
api_data[:bar] = bar
api_data[:batz] = batz

api_data.reject! { |_, value| value.nil? }

会起作用。

0

不能说我喜欢这个解决方案,但无论如何:

Hash[[:foo, :bar, :baz].find_all { |var| eval var.to_s }.map { |var| [var, eval(var.to_s)] }]

0
你可以像下面这样做:
["foo", "bar", "batz"].each do |v|
    eval(v).tap {|val| api_data[v.to_sym] = val if val }
end

-1

这里有一个使用 Array#compactEnumerable#each_with_object 的例子:

[foo, bar, batz].compact.each_with_object(api_data) {|elem, acc| acc.merge!({elem => elem})}

[foo, bar, batz].compact 返回已删除 nil 的输入数组,您正在将输入数组中的每个非空元素合并到作为初始值传递给 each_with_objectapi_data 哈希中。


我刚看到这个!不知道为什么这个答案被踩了!请随意提供任何反馈。 - vee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接