2016-12-20 26 views
2

我有一個從CSV文件中提取的數千個ID(現在它是一個ID的生成器)來迭代和處理這些ID。避免發生器分配器產生無值

爲了優化代碼,我已經將這些ID分組在批次中並一次處理整個批次。

以下代碼分區 - 批量大小爲n的生成器。

from itertools import zip_longest 
def grouper(n, iterable): 
    """ Grouping of iterable with n objects 
     Attributes 
     :n No. of values in a group 
     :iterable/string to be iterated 
     :return group of string/iterator values 
    "grouper(3, 'abcdefg') --> ('a','b','c'), ('d','e','f'), ('g',None, None)" 
    """ 
    return zip_longest(*[iter(iterable)]*n) 

如:

>>>acc_ids = ['ID21', 'ID24', 'ID38', 'ID40', 'ID42', 'ID43', 'ID47', 'ID54', 'ID58'] 
#--As an iterator 
>>>id_generator = (i for i in acc_ids) 
>>>batches = grouper(7, id_generator) 
>>>batches 
<itertools.zip_longest object at 0x7f3beb3313b8> 
#This iterator is much similar to the below list and notice padded `None`(s) at the end of last batch: 
#[('ID21', 'ID24', 'ID38', 'ID40', 'ID42', 'ID43', 'ID47'), ('ID54', 'ID58', None, None, None, None, None)] 

這裏的問題是,要從迭代填充None值我使用filter

for batch in batches: 
    batch = list(filter(None, batch)) 

這個過濾器從列表中刪除None值。因爲我想,而不是增加額外的過濾器,才能夠防止而分裂發生器產生填充None值...

查詢:

  • 是否有任何其他的方式來分割大發生器產生批次 ,而不在最後一批末尾添加無/無值。
  • 我們是否可以改變上面的函數grouper來抑制產生填充無值?
+1

*「但是這個過濾器返回了一個列表」*,在Python 3中,它不返回一個列表,返回一個「過濾器」對象。 –

+0

Python 3中'filter'的文檔「返回一個產生這些迭代項的迭代器...」 –

+0

@ JimFasarakis-Hilliard:對不起,看起來像是我將它轉換爲列表以激發HTTP API調用,我將更新我只想刪除填充無值的問題。並且必須避免使用過濾器 –

回答

3

這可能會爲你工作:

def grouper(n, iterable): 
    iter_ = iter(iterbale) 
    while True: 
     res = tuple(next(iter_) for _ in range(n)) 
     if not res: 
      return 
     yield res 


acc_ids = ['ID21', 'ID24', 'ID38', 'ID40', 'ID42', 'ID43', 'ID47', 'ID54', 'ID58'] 
id_generator = iter(acc_ids) 
batches = grouper(7, id_generator) 
print(list(batches)) 

輸出:

[('ID21', 'ID24', 'ID38', 'ID40', 'ID42', 'ID43', 'ID47'), ('ID54', 'ID58')] 
+0

這是否適合您? –

+0

而不是'提升StopIteration',''return'會更好(是的,只是沒有返回)。 'raise StopIteration'由於(可能是好的)原因而被棄用。 – MSeifert

+0

@ MSeifert是的,看起來更漂亮。改變。謝謝。 –

1

一種可能性是使用已經包含了這樣的功能的外部庫:

  • iteration_utilities.grouper

    >>> from iteration_utilities import grouper 
    >>> list(grouper(acc_ids, 7)) 
    [('ID21', 'ID24', 'ID38', 'ID40', 'ID42', 'ID43', 'ID47'), ('ID54', 'ID58')] 
    
  • more-itertools.chunked

    >>> from more_itertools import chunked 
    >>> list(chunked(acc_ids, 7)) 
    [['ID21', 'ID24', 'ID38', 'ID40', 'ID42', 'ID43', 'ID47'], ['ID54', 'ID58']] 
    
  • pytoolz.partition_allcytoolz.partition_all

    >>> from toolz import partition_all 
    >>> list(partition_all(7, acc_ids)) 
    [('ID21', 'ID24', 'ID38', 'ID40', 'ID42', 'ID43', 'ID47'), ('ID54', 'ID58')] 
    

這些庫都有自由的許可(Apache的,MIT和BSD),所以即使你不」不想要依賴關係,你可能只是重用他們的代碼(你可能需要在你的c中包含他們的許可證)儘管如此,請參閱他們的許可證瞭解更多詳情)。