Ruby中的inject和daisy chaining?

3

我不确定这是什么语法,但让我给你展示一下问题。

def factors num
  (1..num).select {|n| num % n == 0}
end

def mutual_factors(*nums)
  nums
    .map { |n| factors(n) }
    .inject(:&)
end




p mutual_factors(50, 30)            # [1, 2, 5, 10]
p mutual_factors(50, 30, 45, 105)   # [1, 5]
p mutual_factors(8, 4)              # [1, 2, 4]
p mutual_factors(8, 4, 10)          # [1, 2]
p mutual_factors(12, 24)            # [1, 2, 3, 4, 6, 12]
p mutual_factors(12, 24, 64)        # [1, 2, 4]
p mutual_factors(22, 44)            # [1, 2, 11, 22]
p mutual_factors(22, 44, 11)        # [1, 11]
p mutual_factors(7)                 # [1, 7]
p mutual_factors(7, 9)              # [1]


在这部分中,需要进行质疑的是:
nums
  .map { |n| factors(n) }
  .inject(:&)

好的,这是我的思路:首先,map使用辅助方法获取因子,并将因子输出到另一个数组中,然后该数组被注入?

我认为

.inject(:&)

这里让我感到困惑。我在Google上快速搜索了一下,但除了对数组求和和基本操作之外,我很少使用“inject”。我也做过类似以下的事情:

test =  "hello".split("").map(&:upcase)
p test.join

但是 .inject(:&) 是什么意思呢?我知道 & 是一个 proc,但我只在参数中使用过它们。我不知道底层的基础知识,请考虑我的当前水平来解释这个问题 =) 我知道基本的 inject 如何工作,也知道 splat 运算符。

.inject(:&) is equivalent to .inject { |memo, obj| memo.public_send(:&, obj)} - Stefan
1个回答

5

摘自Enumerable#inject文档的部分内容。

inject(symbol) → object

[...]

Returns an object formed from operands via either:

A method named by symbol.

[...]

With method-name argument symbol, combines operands using the method:

# Sum, without initial_operand.
(1..4).inject(:+)     # => 10

这意味着在 inject 的上下文中,(:&) 不是一个过程(proc),而仅仅是告诉 inject 要执行什么操作来组合数组中的元素的符号 :&

让我们看一个例子:

mutual_factors(8, 4, 10)
#=> [1, 2]

现在让我们看看每个步骤会发生什么:

nums
  .map { |n| factors(n) } #=> [[1, 2, 4, 8], [1, 2, 4], [1, 2, 5, 10]]
  .inject(:&)             #=> [1, 2, 4, 8] & [1, 2, 4] & [1, 2, 5, 10]

Array#& 是一个方法,返回一个新的数组,其中包含两个数组中都存在的每个元素(重复的元素会被省略)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接