Pythonでコードを書くのに多くの時間を費やしているように感じますが、Pythonicコードの作成には十分な時間ではありません。最近、私は簡単で慣用的な解決策があるかもしれないと思った面白い小さな問題に遭遇しました。オリジナルを言い換えると、リスト内のすべての順次ペアを収集する必要がありました。たとえば、_[1,2,3,4,5,6]
_というリストがある場合、[(1,2),(3,4),(5,6)]
を計算したいと思いました。
当時、私は翻訳されたJavaのように見える簡単な解決策を思いつきました。質問を振り返って、私ができる最善のことは
_l = [1,2,3,4,5,6]
[(l[2*x],l[2*x+1]) for x in range(len(l)/2)]
_
これには、長さが均一でない場合に最後の数値を投げるという副作用があります。
私が見逃しているもっと慣用的なアプローチはありますか、それともこれが私が得る最高のものですか?
これはもう少しきれいにそれをします:
>>> data = [1,2,3,4,5,6]
>>> Zip(data[0::2], data[1::2])
[(1, 2), (3, 4), (5, 6)]
(ただし、範囲の「ストライド」機能に慣れていない場合は、おそらく読みにくくなります)。
コードと同様に、奇数の値がある最後の値を破棄します。
よく引用されるのは:
Zip(*[iter(l)] * 2)
私はiter
ソリューションのより読みやすいバージョンを好みます:
it = iter(l)
list(Zip(it, it))
# [(1, 2), (3, 4), (5, 6)]
私は通常、grouper
レシピを itertools ドキュメントから私のコードにコピーします。
def grouper(n, iterable, fillvalue=None):
"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)
range()
のステップ機能を使用するのはどうですか?
[(l[n],l[n+1]) for n in range(0,len(l),2)]
正しいことは、おそらくリストを計算することではなく、反復子->反復子関数を書くことです。これはより一般的です-すべての反復可能オブジェクトで機能し、リストに「フリーズ」したい場合は、「list()」関数を使用できます。
def groupElements(iterable, n):
# For your case, you can hardcode n=2, but I wanted the general case here.
# Also, you do not specify what to do if the
# length of the list is not divisible by 2
# I chose here to drop such elements
source = iter(iterable)
while True:
l = []
for i in range(n):
l.append(source.next())
yield Tuple(l)
Itertoolsモジュールがそのための機能をまだ持っていないことに驚いています-おそらく将来のリビジョンです。それまでは、上記のバージョンを自由に使用してください:)
これを試して
_def pairs(l, n):
return Zip(*[l[i::n] for i in range(n)])
_
そう、
pairs([1, 2, 3, 4], 2)
は
_[(1, 2), (3, 4)]
_
リスト内の要素の数がこれでなくても要素を失いたくない場合:
>>> l = [1, 2, 3, 4, 5]
>>> [(l[i], l[i+1] if i+1 < len(l) else None) for i in range(0, len(l), 2)]
[(1, 2), (3, 4), (5, None)]