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

How does using Array#reduce in this way work?

过去几周我一直在学习 ruby,我遇到了类似这样的事情:

array = [10, 20, 20];

array.reduce(:^)

# => 10

评估为 10。

该代码的目的是在 [10, 20, 20].

等序列中查找出现次数为奇数的元素

有没有人对它的工作原理有一个相对简单的解释?

Fixnum#^ 按位异或 运算符 (XOR)。

(10 ^ 20) ^ 20 #=> 10

不过,我不确定您如何过滤出现次数为奇数的数字。

reduce combines all the elements of an Enumerable by applying a binary operation. ^ 是按位异或 (XOR) 运算符。

array.reduce(:^)array 的元素执行按位异或。对于 array = [10, 20, 20],执行 (10 ^ 20) ^ 20,给出结果 10

一个数和它本身的按位异或为0并且异或是关联的(顺序不重要)。因此,数组中的每一对相同数字都被抵消,留下出现奇数次的任何数字的异或。如果数组中有一个数字出现奇数次,那么这个数字就是结果。

array = [10, 20, 20];

array.reduce(:^)
  #=> 10

产生与

相同的结果
array.reduce { |t,n| t^n }
  #=> 10

让我们添加一个 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

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

Fixnum#^ is the bitwise "exclusive-or" 运算符 (XOR).

t #=> 10和(第一个)n #=> 20被传递到区块时:

t^n #=> 30

因为

10.to_s(2)      #=> "01010" 
20.to_s(2)      #=> "10100"
                     ----- 
(10^20).to_s(2) #=> "11110"
"11110".to_i(2) #=>     30
10^20           #=>     30

t #=> 30和(第二个)n #=> 20被传递到区块时:

t^n #=> 10

因为

30.to_s(2)      #=> "11110" 
20.to_s(2)      #=> "10100" 
                     ----- 
(30^20).to_s(2) #=> "01010" 
"1010".to_i(2)  #=>     10     
(30^20)         #=>     10