2016-12-20 5 views
2

これらのIDを繰り返し処理するために、CSVファイルから数千のIDを抽出しました(現在はIDジェネレータです)。ジェネレータスプリッタを使用せずにNone値を生成する

コードを最適化するために、これらの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値を生成防ぐことができます...

クエリ:

  • 生成するために、大きな発電機を分割する他のアプローチがありますバッチ 最後のバッチの終わりにNone/Null値を追加しないでください。
    または
  • 上記の機能をgrouperに変更して、パッドなしの値を生成することはできますか?
+1

* "このフィルタは私にリストを返す" *、Python 3ではリストを返さず、 'filter'オブジェクトが返されます。 –

+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

'raise 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_allまたはcytoolz.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もっと詳細についてはライセンスを参照してください)。

関連する問題