2015-01-13 178 views
1

Python的itertools模塊通過使用生成器來處理iterable/iterator方面提供了很多好處。什麼是Python的Python等價物itertools.chainPython`itertools.chain`的Ruby等價物是什麼?

+2

您可能想要解釋「itertools.chain」的作用 - 並非每位Ruby專家都知道Python。 –

+0

@FrankSchmitt它生成一個迭代器,它可以順序地鏈接兩個或更多現有的迭代器,即從一個迭代器直到耗盡,然後從另一個迭代器產生值,依此類推。 – user4815162342

回答

3

我不是一個Ruby程序員,但我覺得這樣的事情應該這樣做:

def chain(*iterables) 
    for it in iterables 
     if it.instance_of? String 
      it.split("").each do |i| 
       yield i 
      end 
     else 
      for elem in it 
       yield elem 
      end 
     end 
    end 
end 

chain([1, 2, 3], [4, 5, 6, [7, 8, 9]], 'abc') do |x| 
    print x 
    puts 
end 

輸出:

1 
2 
3 
4 
5 
6 
[7, 8, 9] 
a 
b 
c 

如果你不想壓平串,然後使用Array#flatten這可以縮寫爲:

def chain(*iterables) 
    return iterables.flatten(1) # not an iterator though 
end 
print chain([1, 2, 3], [4, 5, 6, [7, 8, 9]], 'abc') 
#[1, 2, 3, 4, 5, 6, [7, 8, 9], "abc"] 
1

Python迭代器的Ruby等價物是Enumerator。沒有爲鏈接兩個Enumerator沒什麼方法,但可以很容易地編寫像這樣:

class Enumerator 
    def chain(*others) 
    self.class.new do |y| 
     [clone, *others.map(&:clone)].each do |e| 
     loop do y << e.next end 
     end 
    end 
    end 

    def +(other) 
    chain(other) 
    end 
end 

e1 = %w[one two].each 
e2 = %w[three four].each 
e3 = %w[five six].each 

e = e1.chain(e2, e3) 

e.map(&:upcase) 
# => ['ONE', 'TWO', 'THREE', 'FOUR', 'FIVE', 'SIX'] 
0

Python docs for itertools.chain

請返回從第一個迭代的元素,直到 它是一個迭代用盡,然後繼續下一個迭代,直到所有的迭代器都耗盡。用於將連續序列作爲 單一序列進行處理。

首先,在Python

from itertools import chain 

# nested arrays 
iterables = [ 
       ["one", "two"], 
       ["three", "four"], 
       ["five", "six", "6", ["eight", "nine", "ten"]] 
      ] 

list(chain(*iterables)) 

輸出的例子:

['one', 'two', 'three', 'four', 'five', 'six', '6', ['eight', 'nine', 'ten']] 

我學習Ruby,所以我試圖使用從Python文檔的代碼示例複製行爲:

# taken from Python docs as a guide 
def chain(*iterables): 
    # chain('ABC', 'DEF') --> A B C D E F 
    for it in iterables: 
     for element in it: 
      yield element # NOTE! `yield` in Python is not `yield` in Ruby. 
      # for simplicity's sake think of this `yield` as `return` 

我的Ruby代碼:

def chain(*iterables) 
    items = [] 
    iterables.each do |it| 
    it.each do |item| 
     items << item 
    end 
    end 
    items 
end 

nested_iterables = [%w[one two], %w[three four], %W[five six #{3 * 2}]] 
nested_iterables[2].insert(-1, %w[eight nine ten]) 

puts chain(*nested_iterables) 

# and to enumerate 
chain(*nested_iterables).each do |it| 
    puts it 
end 

兩個輸出:

["one", "two", "three", "four", "five", "six", "6", ["eight", "nine", "ten"]] 
0

代碼

def chain(*aaa) 
    aaa.each { |aa| (aa.class == String ? aa.split(//) : aa).each { |a| yield a } } 
end 

chain([0, 1], (2..3), [[4, 5]], {6 => 7, 8 => 9}, 'abc') { |e| print e, ',' } 

輸出

0,1,2,3,[4, 5],[6, 7],[8, 9],a,b,c, 
相關問題