2016-06-07 62 views
2

我只是想申请一个二进制操作连续数组中的元素,例如:为什么each_cons会产生数组而不是多个值?

[1, 2, 3, 4].each_cons(2).map { |a, b| a.quo(b) } 
#=> [(1/2), (2/3), (3/4)] 

这是一个人为的例子,操作其实并不重要。

我很惊讶,我不能只是写:

[1, 2, 3, 4].each_cons(2).map(&:quo) 
#=> NoMethodError: undefined method `quo' for [1, 2]:Array 

这是因为each_cons不会产生多个值,但包含值的数组。

它的工作原理是这样的:

def each_cons_arrays 
    return enum_for(__method__) unless block_given? 
    yield [1, 2] 
    yield [2, 3] 
    yield [3, 4] 
end 

each_cons_arrays.map(&:quo) 
#=> NoMethodError: undefined method `quo' for [1, 2]:Array 

而我希望的:

def each_cons_values 
    return enum_for(__method__) unless block_given? 
    yield 1, 2 
    yield 2, 3 
    yield 3, 4 
end 

each_cons_values.map(&:quo) 
#=> [(1/2), (2/3), (3/4)] 

什么是这背后的原理是什么?为什么总是有数组可能更好?

顺便说一下,with_index,另一方面也产生多个值:

[1, 1, 1].each.with_index(2).map(&:quo) 
#=> [(1/2), (1/3), (1/4)] 
+0

如果你正在做'each_cons(3)',期望是什么?你所要求的只适用于'each_cons(2)'。 –

+0

@WandMaker它会产生3个值。当然,这对'quo'不起作用,因为它只需要1个参数。 – Stefan

+1

此外,我认为'each_cons(2)'是一个非常常见的情况。 – Stefan

回答

0

从我的经验,它有助于红宝石认为多个值的数组。

它在为

[1,2,3].each_cons(2) do |iter| 
    a,b = iter 
    do_stuff(a,b) 
end 

如果你想那样做想起来了,我的quo方法添加到自定义类,并做

class Foobar 
    def initialize(a,b) 
    @a = a 
    @b = b 
    end 

    def quo 
    do_stuff 
    end 
end 

[1,2,3] 
    .each_cons(2) 
    .map { |a,b| Foobar.new(a,b) } 
    .map(:quo) 

将这项工作为你的用例?

+3

你的第一个例子只能这样工作,因为'each_cons'产生数组。但是,产生多个值并产生包含这些值的数组是有区别的。例如,'each_with_index' _does_会产生多个值,因此'%w(a b c).each_with_index.map {| e | e]''返回'[“a”,“b”,“c”]',而不是'[[“a”,0],[“b”,1],[“c”,2]]' – Stefan

相关问题