Ruby 什么';这段代码中逗号的作用是什么?

Ruby 什么';这段代码中逗号的作用是什么?,ruby,Ruby,我试图用方法来理解这段代码。每个带有对象的。 我不明白逗号(在units[name]之后)在块内是如何工作的 更清楚地说,它的功能是什么? 为什么有一个逗号将单位[name]与秒数=…分开,而不是写为单位[name,seconds=seconds…” 这是一段代码: units=durations。每个带有_对象({})的|(名称,持续时间),单位| 单位[名称],秒=秒。divmod(持续时间) end.reject{| k,v | v.zero?}.map(&singularize) 在Ru

我试图用方法来理解这段代码。每个带有对象的。 我不明白逗号(在
units[name]
之后)在块内是如何工作的

更清楚地说,它的功能是什么? 为什么有一个逗号将
单位[name]
秒数=…
分开,而不是写为
单位[name,seconds=seconds…”

这是一段代码:

units=durations。每个带有_对象({})的|(名称,持续时间),单位|
单位[名称],秒=秒。divmod(持续时间)
end.reject{| k,v | v.zero?}.map(&singularize)
在Ruby中,您可以通过以下方式“解构”数组并将其绑定到多个变量
a,b=[1,2]
,其中
1
将绑定到
a
2
b
。举个例子:

[1] pry(main)> a, b = [1, 2]
=> [1, 2]
[2] pry(main)> a
=> 1
[3] pry(main)> b
=> 2
知道这一点,上述代码与

units=durations。每个带有_对象({})的|(名称,持续时间),单位|
结果=秒。divmod(持续时间)
单位[名称]=结果。第一个
秒=result.last
结果
end.reject{| k,v | v.zero?}.map(&singularize)
思考您的问题时,
单位[name,seconds=seconds….]
无效。散列的
[]
方法只需要一个参数。您可以定义自己的类来接受更多

# The following was tested on ruby 2.6

class A
  def [](name, surname)
    puts "#{name} #{surname}"
  end

  def []=(name, surname, value)
    puts "#{name} #{surname} = #{value}"
  end
end

a = A.new
a['foo', 'bar'] # prints 'foo bar'
a['foo', 'bar'] = 'baz' # prints 'foo bar = bar'
因此,您可以定义自己的哈希实现来实现您所描述的功能,但默认情况下它不会。

似乎
.map(&singularize)
与这个问题并不相关,所以我将其删除

样本数据

让我们分析一下这个代码片段。为此,我们需要一些数据。我猜,
持续时间
可能看起来像下面这样,但实际结构可能并不重要

seconds = 1630
durations = [["Bob", 3600], ["Melba", 60]] 
鲍勃以小时为单位消耗时间;梅尔巴,几分钟后

枚举数

我们首先定义一个枚举数

enum = durations.each_with_object({})
  #=> #<Enumerator: {"Bob"=>3600, "Melba"=>60}:each_with_object({})>
数组分解

分解
enum.next的过程被调用。这个链接值得仔细阅读。事实上,整个文件编写得很好,内容丰富。请注意
|(名称、持续时间)、单位|
中的括号如何与数组
持续时间
中的括号相对应。另见

块计算

现在可以执行块计算

units[name], seconds = seconds.divmod(duration)
  #=> units["Bob"], seconds = 1630.divmod(3600)
  #=> units["Bob"], seconds = [0, 1600]
units
  #=> {"Bob"=>0} 
seconds
  #=> 1630 
我们再次使用了数组分解。由于
duration
等于Bob(3600)的每小时秒数,
units[“Bob”]
设置为等于他“消耗”的小时数,
seconds
现在等于剩余秒数。由于后者保持不变(
1630
),我们推断Bob只能以小时的倍数消耗时间,因此他消耗了零秒

{"Bob"=>0, "Melba"=>27}.reject { |k, v| v.zero? }
  #=> {"Melba"=>27}
枚举生成的第二个值

在块通知enum它已准备好生成另一个元素之后,我们有以下步骤

(name, duration), units = enum.next
  #=> [["Melba", 60], {"Bob"=>1}] 
name
  #=> "Melba" 
duration
  #=> 60 
units
  #=> {"Bob"=>0} 
请注意,
单位
已更新。继续

units[name], seconds = seconds.divmod(duration)
  #=> units["Melba"], seconds = 1630.divmod(60)
  #=> units["Melba"], seconds = [27, 10]
units
  #=> {"Bob"=>0, "Melba"=>27}
seconds
  #=> 10
我们看到梅尔巴消耗了
27
分钟的
1630
秒,剩下
10

块从
enum
请求下一个元素

块现在可以从
enum
获取另一个元素

(name, duration), units = enum.next    
   #=> #StopIteration (iteration reached an end)
enum
引发了一个
stopInteraction
异常,因为它没有更多的元素可提供。这导致块返回
单位的值(
{“Bob”=>0,“Melba”=>27}

删除非时间消费者

最后,我们摆脱了所有消耗零秒的人

{"Bob"=>0, "Melba"=>27}.reject { |k, v| v.zero? }
  #=> {"Melba"=>27}
更复杂的数组分解示例

这里有两个

arr = [[1, {a:2}, [3, [4, 5..6]]], 7]

(a, b, (c, (d, e))), f  = arr
a #=> 1 
b #=> {:a=>2} 
c #=> 3 
d #=> 4 
e #=> 5..6 
f #=> 7

[arr].each do |(a,b,(c,(d,e))),f|
  puts a
  puts b
  puts c
  puts d
  puts e
  puts f
end
1
{:a=>2}
3
4
5..6
7
再次将括号的位置与
arr
中括号的位置进行比较


数组分解的使用非常有用,但似乎没有得到充分利用。

非常感谢您的评论,它对理解Ruby中的语法非常有帮助。谢谢Shello Cary非常感谢您的时间和非常完整的解释。我已经保存了你建议的一些链接。谢谢