【问题标题】:Inject with embedded conditional...possible?注入嵌入式条件......可能吗?
【发布时间】:2013-08-29 23:52:49
【问题描述】:

我期待9,但得到nil。不知道为什么。

> dfs = p.disk_items.inject { |acc, di| acc + 1 if di.type == "DiskFile" }
=> nil

同样的问题:

> dfs = p.disk_items.inject(0) { |acc, di| if di.type == "DiskFile" then acc + 1 end } 
=> nil

很明显,di.type == "DiskFile" 为真有九次:

> dfs = p.disk_items.inject(0) { |acc, di| puts di.type == "DiskFile" }
true
true
true
true
true
true
true
true
true
false
=> nil

我在搞砸什么?如果我不能使用条件,那么也许有更好的方法来计算数组中满足属性条件的所有 ActiveRecord 对象。

编辑:FWIW:

> p.disk_items.class
=> ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_DiskItem

看起来this implementation in Rails sourcecount 可能不接受块?虽然我可能读错了或者看错了地方......

【问题讨论】:

  • if“不运行”时,块评估为nil
  • 嗯,所以如果块评估为零,acc 应该仍然有一个值,我认为这是 inject 返回的值?!?无论如何,有没有更好的方法来做到这一点?
  • 值 [returned] 现在是 nil - 结果(或下一个 acc 将是 nil)。是的,有更好的方法。更新了我的答案。

标签: ruby-on-rails ruby iterator inject


【解决方案1】:

user2246674 是正确的,if 语句返回 nil,但 inject 应该总是返回 acc 您可以使用 turnery 运算符来简化此操作

dfs = p.disk_items.inject(0) { |acc, di| di.type == "DiskFile" ? acc + 1 : acc  }

【讨论】:

  • 我尝试在 false 上返回 0 的三元组,但我现在看到,计数器应该被返回......我现在明白了!谢谢!
  • 哎呀。当我尝试使用这种三元语法时,似乎收到了 NoMethodError: undefined method '+' for #<DiskFile:0x007ff9c63f9658> 错误。
  • @Meltemi 因为代码缺少默认的 (0) 累加器(假设序列中的第一次也是如此)。我已经更正了。
  • 哈,谢谢。只是从第一个示例中复制了它。不过确实,user2246674 是对的,count 可能是在这种情况下使用的正确方法
  • 设置累加器的起始值,inject(0),做到了! (虽然我认为0 是默认的?!?无论如何,谢谢。
【解决方案2】:

if“不运行”时,块评估为nil。这发生在最后一种情况下,并返回结果 (nil)。

考虑(长手):

if di.type == "DiskFile" then
    acc + 1
else
    acc      # so we never return nil
end

虽然有各种简写形式(即 ?:),但我会使用 count {block}。如果需要对这些值执行其他操作(可能仍在“有时”注入中使用),select 也可能有用。

p.disk_items.count {|di| di.type == "磁盘文件"}

【讨论】:

  • [array].count 应该这样做;忘了那个。 Ruby 中有这么多迭代器。但是,唉,这对我也不起作用……di.type == "DiskFile" 返回10。但di.type == "garbage00jfsledl" 也是如此。期待9
  • @Meltemi 我没想到会有这些结果。有点不对劲。
  • 查看我的编辑(上图)。也许我误解了 Rails 源代码;如我错了请纠正我。我所知道的是,无论我在块count 中放入什么,都只会返回集合中的数量......好像块不存在一样。
  • @Meltemi 我不使用 Rails,但如果 Enumerable.count {block} 没有因收藏而受到尊重,那就太可惜了。 select {block}/count 对应该可以工作。也许:)
猜你喜欢
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 2011-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多