代码之家  ›  专栏  ›  技术社区  ›  Dexygen

为什么UNIQ?如果没有重复项,则返回nil

  •  11
  • Dexygen  · 技术社区  · 15 年前

    我刚从Ruby开始,我个人认为以下内容违反了“最不令人惊讶的原则”。也就是说,引用 the documentation 那是UNIQ!”从自身删除重复元素。如果未做任何更改(即未找到重复项),则返回nil。“

    有人能解释一下吗,这对我来说完全是违反直觉的?这意味着不需要通过附加.uniq来编写下面的一行代码!要结束第一行,我必须写以下两行:

      hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/)
      hooks = hooks.uniq
    

    或者我错过了什么,更好的方法?

    编辑:

    我理解联合国国际质量机构!修改其操作数。以下是我希望能更好地说明的问题:

      hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/)
      puts hooks.length #50
      puts hooks.uniq!.length #undefined method `length' for nil:NilClass
    

    我认为这是联合国国际质量机构的做法!工作使它完全没有意义和无用。当然,在我的例子中,正如所指出的,我可以在第一行附加.uniq。不过,在同一个程序的后面,我将元素推送到循环内的另一个数组中。然后,在循环下,我想“去重复”数组,但我不敢写“hooks-tested.uniq!”因为它可以返回零;相反,我 必须 write hooks_tested=hooks_tested.uniq

    事实上,我认为这是一个特别令人震惊的错误特征,因为众所周知,在设计返回数组的方法时,应该始终至少返回一个空数组,而不是零

    5 回复  |  直到 8 年前
        1
  •  10
  •   Simone Carletti    15 年前

    这是因为 uniq! 修改 self 如果 UNIQ! 将返回一个值,您将无法知道原始对象中是否实际发生了更改。

    var = %w(green green yellow)
    if var.uniq!
      # the array contained duplicate entries
    else
      # nothing changed
    end
    

    在您的代码中,您可以简单地编写

    hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/)
    hooks.uniq!
    # here hooks is already changed
    

    如果需要返回hook的值,可能是因为它是最后一个方法语句

    def method
      hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/)
      hooks.uniq
    end
    

    或以其他方式

    def method
      hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/)
      hooks.uniq!
      hooks
    end
    
        2
  •  5
  •   Mike Woodhouse    15 年前

    感叹号在 uniq! 指示它修改数组而不是返回新数组。你应该这样做:

    hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/).uniq
    

    或者这个

    hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/)
    hooks.uniq!
    puts hooks.length
    
        3
  •  2
  •   Mladen Jablanović    15 年前

    你可以追加 uniq (结尾没有感叹号)到第一行的结尾。

    或者,如果你坚持使用 uniq! 使用

    (hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/)).uniq!
    
        4
  •  1
  •   ahnbizcad    8 年前

    这不是解决原因的答案,而是解决方法。

    自从 uniq 不回来 nil 我用 UNIQ 并将结果赋给一个新的变量,而不是使用bang版本

    original = [1,2,3,4]
    new = original.uniq
    
    #=> new is [1,2,3,4]
    #=> ... rather than nil
    

    拥有一个新的变量是一个很小的代价。它当然比做if检查要好,重复复杂的调用 uniq! UNIQ 并检查

        5
  •  1
  •   mwp    8 年前

    从Ruby 1.9开始, Object#tap 可用:

    hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/).tap do |hooks|
      hooks.uniq!
    end
    puts hooks.length
    

    也许更简洁(h/t@aetherus):

    hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/).tap(&:uniq!)
    puts hooks.length