如何使用Array#reduce以这种方式工作?

hel*_*re1 3 ruby reduce inject

我过去几周一直在学习红宝石,我遇到过类似的东西:

array = [10, 20, 20];

array.reduce(:^)

# => 10
Run Code Online (Sandbox Code Playgroud)

评估为10.

代码的目的是在序列中找到一个奇数出现的元素,例如[10, 20, 20].

有没有人对这是如何工作有一个相对简单的解释?

Car*_*and 7

array = [10, 20, 20];

array.reduce(:^)
  #=> 10
Run Code Online (Sandbox Code Playgroud)

产生与...相同的结果

array.reduce { |t,n| t^n }
  #=> 10
Run Code Online (Sandbox Code Playgroud)

让我们添加一个puts声明,看看发生了什么.

array.reduce do |t,n|
  puts "t = #{t}, n = #{n}, t^n = #{t^n}"
  t^n
end
  # t = 10, n = 20, t^n = 30
  # t = 30, n = 20, t^n = 10
  #=> 10
Run Code Online (Sandbox Code Playgroud)

当Enumerable #intil没有给出参数时,"memo"(块变量t)被设置为等于receiver(10)的第一个元素,并且传递给块的第一个元素是接收器的第二个元素,20.

Fixnum#^是按位"异或"运算符(XOR).

当t #=> 10和(第一个)n #=> 20传递给块时:

t^n #=> 30
Run Code Online (Sandbox Code Playgroud)

因为

10.to_s(2)      #=> "01010" 
20.to_s(2)      #=> "10100"
                     ----- 
(10^20).to_s(2) #=> "11110"
"11110".to_i(2) #=>     30
10^20           #=>     30
Run Code Online (Sandbox Code Playgroud)

当t #=> 30和(第二个)n #=> 20传递给块时:

t^n #=> 10
Run Code Online (Sandbox Code Playgroud)

因为

30.to_s(2)      #=> "11110" 
20.to_s(2)      #=> "10100" 
                     ----- 
(30^20).to_s(2) #=> "01010" 
"1010".to_i(2)  #=>     10     
(30^20)         #=>     10
Run Code Online (Sandbox Code Playgroud)