【问题标题】:Drop value in parallel assignment在并行赋值中删除值
【发布时间】:2017-02-28 13:24:46
【问题描述】:

既然可以这样并行赋值,

x, y, z = [1, 2, 3]

我想知道是否可以删除例如y 值。有没有办法在不污染当前作用域的命名空间的情况下进行并行赋值?

我尝试分配给nil

x, nil, z = [1, 2, 3]

但这不起作用。

【问题讨论】:

    标签: ruby variable-assignment


    【解决方案1】:

    这样做的惯用方法是将其分配给名为下划线的变量:

    x, _, z = [1, 2, 3]
    

    如果要删除多个值,可以使用 splat:

    x, *_, z = [1, 2, 3, 4, 5]
    

    【讨论】:

    • 对于多个值,* 就足够了。或者,为了明确说明被抛出的变量数量,_ 具有特殊的语法,可以在赋值中重复。 x, _, _, _, z = [1, 2, 3, 4, 5].
    • @sawa,单曲* 的重点。我不会编辑我的答案,以免过时 AKovtunov 的答案。至于多个_s - 它更多地取决于你想说的IMO。你是想说z 是最后一个元素还是第五个元素?
    • @sawa:_AFAIK 没有什么特别之处。 x, y, y, y, z = [1, 2, 3, 4, 5] 是一种有效但令人困惑的语法。 y 设置为 4
    • 有趣的是,重复的问题经常会带来很多支持。我有一个很好的答案徽章“3/2 是 1,而不是 1.5”:)。不管怎样,你很快就会得到你的 Ruby 金色徽章。 ;)
    • @EricDuminil,不知道重复的问题,但非常基本的问题 - 确实,令人沮丧。至少在短期内,一个帖子会获得多少赞的主要指标是有多少人会阅读和理解它。这是 SO 游戏化系统的失败之一。 :/ 还是谢谢。
    【解决方案2】:

    正如@ndn 所说,_ 经常被使用。

    忽略它并重新分配它是可以的,但_ 仍然是当前作用域的命名空间中的变量:

    l = [1, 2, 3]
    
    x, _, z = l
    puts _
    #=> 2
    

    如果它困扰你,你可以使用:

    x, z = l.values_at(0,-1)
    

    虽然它可能不太可读。如果您在脚本上启动 rubocop_ 也是建议的语法。

    谈到可读性,如果你想解释变量是什么,但仍然想表明它以后不会被使用,你可以使用:

    x, _y, z = [1, 2, 3]
    # Do something with x and z. Ignore _y
    

    也是 rubocop 提出的:

    test.rb:2:4: W: Useless assignment to variable - y. Use _ or _y as a variable name to indicate that it won't be used.
    

    【讨论】:

      【解决方案3】:

      meschi 曾询问是否有可能使用并行赋值将数组中的一些(但不是全部)元素分配给变量。

      首先,写是没有用的

      a, _, c = [1, true, 2]
      

      因为_ 是一个变量:

      _ #=> true
      

      (您不会使用 IRB 获得此结果,因为 IRB 将_ 用于其自身目的。)

      如果,在上述数组中,您只想将1true 分配给您可以编写的变量

      a, b, * = [1, true, 2]
      a #=> 1
      b #=> true
      

      如果你只想将12分配给变量,你可以写

      a, *, b = [1, true, 2]
      a #=> 1
      b #=> 2
      

      如果对于数组[1, true, 2, 3],您只想将12 分配给变量,那么这就是个问题。显然,正如@Eric 在评论中指出的那样,你需要写

      a, b, b, * = [1, true, 2, 3]
      a #=> 1
      b #=> 2
      

      这个想法当然可以推广:

      a, b, b, b, c, c = [1, true, 2, 3, 4, 5]
      a #=> 1
      b #=> 3
      c #=> 5
      

      这是个好主意吗?那不是问题。

      主要问题可能是创建一个不被使用的变量,然后无意中使用它,如下所示:

      a, _, b = [1, true, 2]
      ...
      launch_missiles_now?(_)
      

      如果是这样,有几个选项。一种是简单地将表达式包装在一个方法中,从而严格限制多余的变量:

      def get_a_and_b(arr)
        a, _, b, _ = arr
        [a, b]
      end
      
      a, b = get_a_and_b [1, true, 2, 3]
        #=> [1, 2]
      

      另一个是命名不需要的变量,以防止它们被意外引用,例如:

      a, _reference_this_variable_and_you_will_die, b = [1, true, 2] 
      

      【讨论】:

        【解决方案4】:

        我更愿意改进@ndn 答案并仅使用* 符号来删除值。 _ 通常用于返回最后一个值,所以在这里使用它可能会造成混淆。

        所以你可以使用

        x, *, z = [1, 2, 3]
        

        还有

        x, *, y, z = [1, 2, 3, 4]
        

        它仍然会理解你并为所有变量返回正确的值。

        【讨论】:

        • * 表示此处将任意数量的变量作为单个数组分配。如果您明确知道只有一个术语,那么_ 更具体,因此更可取。
        • "_ [is] 通常用于返回 [the] 最后一个值,因此在这里使用它可能会造成混淆。"--您这样做的依据是什么?据我所知,这是错误的。
        • 我也想知道_ usually used to return last value来自哪里
        • _ 表示 IRB 和 PRY 中的最后一个值。不过,它在每个 ruby​​ 脚本中都意味着“忽略我”。您甚至可以在 PRY 中使用 __ 倒数第二个。
        • 您似乎混淆了$__。他们不一样。 $_ 是一个全局变量,包含从控制台读取的最后一行或逐行读取文件时。 _ 是一个“slush”或“blackhole”变量,当我们打算丢弃一个值时使用。您所争论的观点与经验丰富的 Ruby 程序员相矛盾。
        猜你喜欢
        • 1970-01-01
        • 2010-09-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多