2013-06-02 9 views
11

私は、Pythonにかなり新たなんだ、これはかなり一般的な問題にすべきだと思いますが、解決策を見つけることができません。私はすでにthis pageを見て、それが1つの項目に役立つことを発見しましたが、私は 'for'ループを使用せずに複数の項目にその例を拡張しようとしています。私はEmceeを通じて250人の歩行者のためにこのコードを実行していますので、私は可能な限り最速の方法を探しています。私は、(例えば)b = [1,2,3]回を繰り返したいが掛けn回

私は番号のリストを持って、a = [x,y,z]ので、私はリストのリストで終わる:私が持っている

[ 
[x], 
[y,y], 
[z,z,z] 
] 

「の」ループは次のようになります。

c = [ ] 
for i in range (0,len(a)): 
    c.append([a[i]]*b[i]) 

私がしたいことはまったく同じですが、私のコードはひどく遅くなっています。私はまた素朴に配列にaとbを入れて、要素で要素を掛けることを期待して[a]*bを実行しましたが、喜びはありません。

あなたがここに zipとリストの内包表記を使用することができます

答えて

10

>>> a = ['x','y','z'] 
>>> b = [1,2,3] 
>>> [[x]*y for x,y in zip(a,b)] 
[['x'], ['y', 'y'], ['z', 'z', 'z']] 

か:

>>> [[x for _ in xrange(y)] for x,y in zip(a,b)] 
[['x'], ['y', 'y'], ['z', 'z', 'z']] 

zipをイテレータの使用にitertools.izip

を取得するために、第1のメモリに全体のリストを作成します。 aにリストやリストのリストのような変更可能なオブジェクトが含まれている場合は、を使用する必要がありますここつのコピーを変更すると、他のコピーが変更されますので:

>>> from copy import deepcopy as dc 
>>> a = [[1 ,4],[2, 5],[3, 6, 9]] 
>>> f = [[dc(x) for _ in xrange(y)] for x,y in zip(a,b)] 

#now all objects are unique 
>>> [[id(z) for z in x] for x in f] 
[[172880236], [172880268, 172880364], [172880332, 172880492, 172880428]] 

timeit比較(輸入を無視して):あなたがそれらを好きではない場合はここで

>>> a = ['x','y','z']*10**4 
>>> b = [100,200,300]*10**4 

>>> %timeit [[x]*y for x,y in zip(a,b)] 
1 loops, best of 3: 104 ms per loop 

>>> %timeit [[x]*y for x,y in izip(a,b)] 
1 loops, best of 3: 98.8 ms per loop 

>>> %timeit map(lambda v: [v[0]]*v[1], zip(a,b)) 
1 loops, best of 3: 114 ms per loop 

>>> %timeit map(list, map(repeat, a, b)) 
1 loops, best of 3: 192 ms per loop 

>>> %timeit map(list, imap(repeat, a, b)) 
1 loops, best of 3: 211 ms per loop 

>>> %timeit map(mul, [[x] for x in a], b) 
1 loops, best of 3: 107 ms per loop 

>>> %timeit [[x for _ in xrange(y)] for x,y in zip(a,b)] 
1 loops, best of 3: 645 ms per loop 

>>> %timeit [[x for _ in xrange(y)] for x,y in izip(a,b)] 
1 loops, best of 3: 680 ms per loop 
+1

私はitertools.izipに言及することをお勧めします。 – kirelagin

+1

ありがとう!しかし、 'for'ループはまだコードを遅くしますか? – user2444731

+0

@ user2444731「遅い」とはどういう意味ですか? 'for'-loopが遅いのはなぜだと思いますか?何に比べて遅い? – kirelagin

1

forループのないバージョンです何らかの理由:

map(lambda v: [v[0]]*v[1], zip(a,b)) 

私はまた、このバージョンは、リスト内包よりも少し遅いことを警告する必要があります

$ a = ['hi']*100 
$ b = [20]*100 

$ %timeit map(lambda v: [v[0]]*v[1], zip(a,b)) 
10000 loops, best of 3: 101 us per loop 

%timeit [[x]*y for x,y in zip(a,b)] 
10000 loops, best of 3: 74.1 us per loop 

私はまた、あなたは、Python 2上にある場合

2

@kirelaginがforループなしバージョンを示唆しitertools.izip代わりのzipを使用することをお勧めしたい、ここにもlambda S(でキープを持たないものです気に@AshwiniChaudharyによって溶液)は

>>> from itertools import repeat 
>>> a = ['x','y','z'] 
>>> b = [1,2,3] 
>>> map(list, map(repeat, a, b)) 
[['x'], ['y', 'y'], ['z', 'z', 'z']] 

>>> map(repeat, a, b) 
[repeat('x', 1), repeat('y', 2), repeat('z', 3)] 
最も読みやすいです

は、Python 2のrepeatオブジェクト(使用imapのリストを作成します。xリストの代わりに怠惰なイテレータが必要な場合)、メモリ内に余分なスペースを占めることはありません。格納する代わりにアイテムを繰り返し処理したい場合に便利です。

5

最も速い方法それはmap()operator.mul()である:

>>> from operator import mul 
>>> map(mul, [['x'], ['y'], ['z']], [1, 2, 3]) 
[['x'], ['y', 'y'], ['z', 'z', 'z']] 
+3

+1あなたが投稿したときにこれを見つけただけです(入力はリストのリストではありません) – jamylak

3
>>> from itertools import repeat 
>>> from itertools import starmap 
>>> a = ['x','y','z'] 
>>> b = [1,2,3] 
>>> starmap(repeat,zip(a,b)) 

starmapは、例えば('x',1)ため、この場合に、タプルに含まれる値に等しい引数でrepeatを呼び出した結果に等しい値を含む反復可能返します。

>>> for p in starmap(repeat,zip(a,b)): 
    print(list(p)) 


['x'] 
['y', 'y'] 
['z', 'z', 'z'] 
+0

'starmap'の' map(list、...) 'をリストのリストを取得する – jamylak