20

Python 2 では、一般的な (古い古い) イディオムは、次のようなmap形式を使用して長さが不均一なイテレータを結合するために使用されます。map(None,iter,iter,...)

>>> map(None,xrange(5),xrange(10,12))
[(0, 10), (1, 11), (2, None), (3, None), (4, None)]

Python 2 では、最長のイテレータが返されるリストの長さになるように拡張され、一方が他方より短い場合は でパディングされNoneます。

Python 3 では、これが異なります。Noneまず、位置 1 の callable の引数として使用することはできません。

>>> list(map(None, range(5),range(10,12)))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable

OK -- 次のように修正できます。

>>> def f(*x): return x    
... 
>>> list(map(f, *(range(5),range(10,12))))
[(0, 10), (1, 11)]

しかし今、私は別の問題を抱えています:最短のイテレータの長さをmap返します.None

私は Python 2 のコードを Python 3 に移植しているので、これはひどい珍しいイディオムではなく、簡単な解決策を見つけていません。

残念ながら、2to3 ツールはこれを検出しません

-map(None,xrange(5),xrange(10,18))
+list(map(None,list(range(5)),list(range(10,18)))) 

提案?


編集

このイディオムがどれほど一般的かについては、いくつかの議論があります。このSO投稿を参照してください

高校生の頃に書いたレガシーコードを更新しています。Raymond Hettinger によって書かれ議論されている 2003 年の Python チュートリアルを見てください。マップのこの特定の動作が指摘されています...

4

4 に答える 4

19

itertools.zip_longestよりわかりやすい名前で、あなたが望むことをします。:)

于 2012-08-18T03:17:58.270 に答える
2

今回は自分の質問に答えます。

Python 3x では、次のようにitertools.zip_longestを使用できます。

>>> list(map(lambda *a: a,*zip(*itertools.zip_longest(range(5),range(10,17)))))
[(0, 10), (1, 11), (2, 12), (3, 13), (4, 14), (None, 15), (None, 16)]

自分でロールすることもできます。

>>> def oldMapNone(*ells):
...     '''replace for map(None, ....), invalid in 3.0 :-( '''
...     lgst = max([len(e) for e in ells])
...     return list(zip(* [list(e) + [None] * (lgst - len(e)) for e in ells]))
... 
>>> oldMapNone(range(5),range(10,12),range(30,38))
[(0, 10, 30), (1, 11, 31), (2, None, 32), (3, None, 33), (4, None, 34), (None, None, 35), (None, None, 36), (None, None, 37)]
于 2012-08-18T07:01:54.920 に答える