リスト内の2つの要素ごとに繰り返す


回答:


231

pairwise()(またはgrouped())実装が必要です。

Python 2の場合:

from itertools import izip

def pairwise(iterable):
    "s -> (s0, s1), (s2, s3), (s4, s5), ..."
    a = iter(iterable)
    return izip(a, a)

for x, y in pairwise(l):
   print "%d + %d = %d" % (x, y, x + y)

または、より一般的には:

from itertools import izip

def grouped(iterable, n):
    "s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), (s2n,s2n+1,s2n+2,...s3n-1), ..."
    return izip(*[iter(iterable)]*n)

for x, y in grouped(l, 2):
   print "%d + %d = %d" % (x, y, x + y)

Python 3ではizip、組み込みzip()関数に置き換えて、を削除できますimport

すべてのクレジットマーティのための彼の答え私の質問は、私はそれが唯一のリストの上に一回反復し、その過程で不要なリストを作成していないとして、これは非常に効率的であることがわかってきました。

注意:これは、コメントで@lazyrによって指摘されている、Python独自のドキュメントpairwiseレシピと混同しないでください。itertoolss -> (s0, s1), (s1, s2), (s2, s3), ...

Python 3 でmypyを使用して型チェックを行いたい人のための少しの追加:

from typing import Iterable, Tuple, TypeVar

T = TypeVar("T")

def grouped(iterable: Iterable[T], n=2) -> Iterable[Tuple[T, ...]]:
    """s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), ..."""
    return zip(*[iter(iterable)] * n)

16
で提案されているペアごとの機能と混同しないようにitertoolsた利回り、レシピセクションs -> (s0,s1), (s1,s2), (s2, s3), ...
Lauritz V.タヴロウ

1
それは別のことをします。このバージョンではitertools、同じ名前のレシピ関数と比較して、ペアの数が半分になります。もちろん、あなたの方が高速です...
Sven Marnach、2011年

え?あなたの機能と私が参照した機能は異なることをするので、それが私のコメントのポイントでした。
Lauritz V. Thaulow

5
注意してください!これらの関数を使用すると、イテラブルの最後の要素を反復しないリスクがあります。例:list(grouped([1,2,3]、2))>>> [(1、2)] ..期待する場合[(1,2)、(3、)]
egafni

4
@ Erik49:質問で指定されたケースでは、「不完全な」タプルがあることは意味がありません。不完全なタプルを含めたい場合は、のizip_longest()代わりに使用できますizip()。例:list(izip_longest(*[iter([1, 2, 3])]*2, fillvalue=0))-> [(1, 2), (3, 0)]。お役に立てれば。
Johnsyweb 2013年

191

2要素のタプルが必要なので、

data = [1,2,3,4,5,6]
for i,k in zip(data[0::2], data[1::2]):
    print str(i), '+', str(k), '=', str(i+k)

どこ:

  • data[0::2] 要素のサブセットコレクションを作成することを意味します (index % 2 == 0)
  • zip(x,y) xコレクションとyコレクションの同じインデックス要素からタプルコレクションを作成します。

8
これは、3つ以上の要素が必要な場合に拡張することもできます。たとえばfor i, j, k in zip(data[0::3], data[1::3], data[2::3]):
ライフバランス2014年

19
インポートを取り込み、関数を定義するよりもずっときれいです!
kmarsh 2014年

7
@kmarsh:ただし、これはシーケンスでのみ機能し、関数はすべての反復可能オブジェクトで機能します。これはO(N)の余分なスペースを使用しますが、関数は使用しません。一方、これは一般的に高速です。どちらか一方を選択するのには十分な理由があります。恐れることはimportそれらの1つではありません。
abarnert 2014

77
>>> l = [1,2,3,4,5,6]

>>> zip(l,l[1:])
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]

>>> zip(l,l[1:])[::2]
[(1, 2), (3, 4), (5, 6)]

>>> [a+b for a,b in zip(l,l[1:])[::2]]
[3, 7, 11]

>>> ["%d + %d = %d" % (a,b,a+b) for a,b in zip(l,l[1:])[::2]]
['1 + 2 = 3', '3 + 4 = 7', '5 + 6 = 11']

1
これはPython-3.6.0では機能していませんが、Python-2.7.10ではまだ機能しています
Hamid Rohani 2017

6
@HamidRohani zipは、zip添え字付きではないPython 3のオブジェクトを返します。これは、配列(に変換する必要があるlisttupleまず、等)が、「動作していないこと」ストレッチのビットです。
vaultah 2017

58

シンプルなソリューション。

l = [1、2、3、4、5、6]

for i(0、len(l)、2)の場合:
    出力str(l [i])、 '+'、str(l [i + 1])、 '='、str(l [i] + l [i + 1])

1
リストが偶数ではなく、最後の番号をそのまま表示したい場合はどうでしょうか。
Hans de Jong

@HansdeJongはあなたを捕まえませんでした。もう少し説明してください。
taskinoor 2014年

2
ありがとう。私はそれを行う方法をすでに理解しました。問題は、リストに含まれる数値の数が少ない場合、インデックスエラーが発生することでした。試してそれを解決しました:例外:
Hans de Jong

または((l[i], l[i+1])for i in range(0, len(l), 2))、ジェネレーターの場合、より長いタプルに簡単に変更できます。
バーゼルシシャニ2015

44

使用zipするすべての答えは正しいですが、自分で機能を実装すると、コードが読みやすくなります。

def pairwise(it):
    it = iter(it)
    while True:
        try:
            yield next(it), next(it)
        except StopIteration:
            # no more elements in the iterator
            return

it = iter(it)パート性を保証it実際にイテレータだけではなく、反復可能です。itすでにイテレータである場合、この行は何もしません。

使用法:

for a, b in pairwise([0, 1, 2, 3, 4, 5]):
    print(a + b)

2
このソリューションにより、タプルのサイズ> 2に一般化することができます
ギロプテロ2015年

1
このソリューションitは、が反復子のみで反復可能でない場合にも機能します。他のソリューションは、シーケンスに対して2つの独立した反復子を作成する可能性に依存しているようです。
15

この答えを見る前に、stackoverflow.com / a / 16815056/2480481でこのアプローチを見つけました。zip()を処理するよりもクリーンで簡単です。
m3nda 2017年

2
受け入れられた答えとして、メモリ使用量が3倍になるのを避けることができるのが好きです。
Kentzo 2018

これは、ジェネレータで発生したものをで置き換えるPEP 479forにより、Python 3.5以降のループではうまく機能しません。StopIterationRuntimeError
シドニー


18

パフォーマンスに興味がある場合simple_benchmarkは、ソリューションのパフォーマンスを比較するために(私のライブラリを使用して)小さなベンチマークを実行し、パッケージの1つの関数を含めました。iteration_utilities.grouper

from iteration_utilities import grouper
import matplotlib as mpl
from simple_benchmark import BenchmarkBuilder

bench = BenchmarkBuilder()

@bench.add_function()
def Johnsyweb(l):
    def pairwise(iterable):
        "s -> (s0, s1), (s2, s3), (s4, s5), ..."
        a = iter(iterable)
        return zip(a, a)

    for x, y in pairwise(l):
        pass

@bench.add_function()
def Margus(data):
    for i, k in zip(data[0::2], data[1::2]):
        pass

@bench.add_function()
def pyanon(l):
    list(zip(l,l[1:]))[::2]

@bench.add_function()
def taskinoor(l):
    for i in range(0, len(l), 2):
        l[i], l[i+1]

@bench.add_function()
def mic_e(it):
    def pairwise(it):
        it = iter(it)
        while True:
            try:
                yield next(it), next(it)
            except StopIteration:
                return

    for a, b in pairwise(it):
        pass

@bench.add_function()
def MSeifert(it):
    for item1, item2 in grouper(it, 2):
        pass

bench.use_random_lists_as_arguments(sizes=[2**i for i in range(1, 20)])
benchmark_result = bench.run()
mpl.rcParams['figure.figsize'] = (8, 10)
benchmark_result.plot_both(relative_to=MSeifert)

ここに画像の説明を入力してください

したがって、外部依存関係のない最速のソリューションが必要な場合は、おそらくJohnyswebが提供するアプローチを使用する必要があります(執筆時点では、これが最も支持され、受け入れられている回答です)。

追加の依存関係を気にしない場合、grouperfrom iteration_utilitiesはおそらく少し速くなります。

追加の考え

一部のアプローチにはいくつかの制限がありますが、ここでは説明していません。

たとえば、いくつかのソリューションはシーケンス(つまり、リスト、文字列など)に対してのみ機能します。たとえば、Margus / pyanon / taskinoorソリューションはインデックスを使用しますが、他のソリューションは反復可能オブジェクト(シーケンスオブジェクトジェネレータ、イテレータ)に対して機能します。 mic_e / myソリューション。

次に、Jonyswebは2以外のサイズでも機能するソリューションを提供しましたが、他の回答では機能しません(そう、 iteration_utilities.grouper、要素の数を「グループ」に設定することもできます)。

次に、リスト内の要素の数が奇数である場合にどうなるかについての質問もあります。残りのアイテムは却下されるべきですか?リストのサイズを均一にするためにリストを埋め込む必要がありますか?残りのアイテムは単一として返されますか?他の答えはこの点に直接対処していませんが、私が何も見落とさなかった場合、それらはすべて残りの項目を却下する必要があるというアプローチに従います(ただし、実際には例外が発生します)。

ではgrouper、あなたは何をしたいかを決めることができます。

>>> from iteration_utilities import grouper

>>> list(grouper([1, 2, 3], 2))  # as single
[(1, 2), (3,)]

>>> list(grouper([1, 2, 3], 2, truncate=True))  # ignored
[(1, 2)]

>>> list(grouper([1, 2, 3], 2, fillvalue=None))  # padded
[(1, 2), (3, None)]

12

zipおよびiterコマンドを一緒に使用します。

私はこのソリューションiterが非常にエレガントであることを見つけます:

it = iter(l)
list(zip(it, it))
# [(1, 2), (3, 4), (5, 6)]

Python 3のzipドキュメントで見つけました。

it = iter(l)
print(*(f'{u} + {v} = {u+v}' for u, v in zip(it, it)), sep='\n')

# 1 + 2 = 3
# 3 + 4 = 7
# 5 + 6 = 11

N一度に要素に一般化するには:

N = 2
list(zip(*([iter(l)] * N)))
# [(1, 2), (3, 4), (5, 6)]

10
for (i, k) in zip(l[::2], l[1::2]):
    print i, "+", k, "=", i+k

zip(*iterable) 各イテラブルの次の要素を持つタプルを返します。

l[::2] リストの1番目、3番目、5番目などの要素を返します。最初のコロンは、後ろに数字がないためスライスが最初から始まることを示します。2番目のコロンは、スライスに「ステップ」が必要な場合にのみ必要です。 '(この場合は2)。

l[1::2]同じことを行いますが、それは第二、第四、第六、などの要素を返しますので、リストの2番目の要素で開始し、元のリストを。


4
この答えは、2年前にマーガスによってすでに与えられました。stackoverflow.com/questions/5389507/...
cababunga

1
[number::number]構文がどのように機能するかを説明するための1 。Pythonをあまり使用しない人に役立つ
Alby

2

開梱あり:

l = [1,2,3,4,5,6]
while l:
    i, k, *l = l
    print(str(i), '+', str(k), '=', str(i+k))

うわー!なぜこれについて考えられなかったのか:)絶対ペアがない場合(奇数のエントリ)を処理する必要がある
Saurav Kumar

1

助けになるかもしれない人のために、これは同様の問題の解決策ですが、(相互に排他的なペアではなく)ペアが重複しています。

Python itertoolsドキュメントから

from itertools import izip

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

または、より一般的には:

from itertools import izip

def groupwise(iterable, n=2):
    "s -> (s0,s1,...,sn-1), (s1,s2,...,sn), (s2,s3,...,sn+1), ..."
    t = tee(iterable, n)
    for i in range(1, n):
        for j in range(0, i):
            next(t[i], None)
    return izip(*t)


1

リストを数値で分割し、このように修正する必要があります。

l = [1,2,3,4,5,6]

def divideByN(data, n):
        return [data[i*n : (i+1)*n] for i in range(len(data)//n)]  

>>> print(divideByN(l,2))
[[1, 2], [3, 4], [5, 6]]

>>> print(divideByN(l,3))
[[1, 2, 3], [4, 5, 6]]

1

それには多くの方法があります。例えば:

lst = [1,2,3,4,5,6]
[(lst[i], lst[i+1]) for i,_ in enumerate(lst[:-1])]    
>>>[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]

[i for i in zip(*[iter(lst)]*2)]    
>>>[(1, 2), (3, 4), (5, 6)]

0

これは、n> 2についての私の一般化を共有するのに適した場所だと思いました。これは、反復可能オブジェクトの単なるスライドウィンドウです。

def sliding_window(iterable, n):
    its = [ itertools.islice(iter, i, None) 
            for i, iter
            in enumerate(itertools.tee(iterable, n)) ]                               

    return itertools.izip(*its)

0

この質問のタイトルは誤解を招く可能性があり、連続するペアを探しているように見えますが、考えられるすべてのペアのセットを反復処理したい場合は、これでうまくいきます。

for i,v in enumerate(items[:-1]):
        for u in items[i+1:]:

0

タイピングを使用すると、mypy静的分析ツールを使用してデータを検証できます。

from typing import Iterator, Any, Iterable, TypeVar, Tuple

T_ = TypeVar('T_')
Pairs_Iter = Iterator[Tuple[T_, T_]]

def legs(iterable: Iterator[T_]) -> Pairs_Iter:
    begin = next(iterable)
    for end in iterable:
        yield begin, end
        begin = end

0

単純化したアプローチ:

[(a[i],a[i+1]) for i in range(0,len(a),2)]

これは、配列がaであり、ペアで反復したい場合に便利です。3つ以上の組み合わせで反復するには、「範囲」ステップコマンドを変更します。次に例を示します。

[(a[i],a[i+1],a[i+2]) for i in range(0,len(a),3)]

(配列の長さとステップが合わない場合は、余分な値を処理する必要があります)


-1

ここではalt_elem、forループに適合するメソッドを使用できます。

def alt_elem(list, index=2):
    for i, elem in enumerate(list, start=1):
        if not i % index:
           yield tuple(list[i-index:i])


a = range(10)
for index in [2, 3, 4]:
    print("With index: {0}".format(index))
    for i in alt_elem(a, index):
       print(i)

出力:

With index: 2
(0, 1)
(2, 3)
(4, 5)
(6, 7)
(8, 9)
With index: 3
(0, 1, 2)
(3, 4, 5)
(6, 7, 8)
With index: 4
(0, 1, 2, 3)
(4, 5, 6, 7)

注:上記のソリューションは、funcで実行される操作を考慮すると効率的ではない場合があります。


-1
a_list = [1,2,3,4,5,6]
empty_list = [] 
for i in range(0,len(a_list),2):
   empty_list.append(a_list[i]+a_list[i+1])   
print(empty_list)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.