2016-11-05 4 views
5

リストがあると、どの2つの非連続アイテム間のすべての組み合わせを取得できますか?2つの非連続アイテムの組み合わせ

たとえば、入力の場合[1, 2, 3, 4, 5]出力を得るにはどうすればよいですか[(1,3), (1,4), (1,5), (2,4), (2,5), (3,5)]

彼らは(互いに隣りすなわち)連続しているので、私はリストに(1,2)(2,3)(3,4)または(4,5)に興味がないんだけど、他のすべては、私が興味を持っています。

これをPythonで行うには、どのような方法がありますか?

+2

'consecutive'手段リストの中で隣り合っているか、直後の数字であるか、自然な麻痺ers? – thefourtheye

+0

@thefourtheyeご協力いただきありがとうございます。連続して私はリストの中でお互いに隣り合っていました。リストは数字ではないかもしれませんが、私は視覚化が容易だと考えました。私はそれをクリアするために質問に何かを追加します。 – faviouz

+1

'itertools'で必要な機能を選択してください:https://docs.python.org/2/library/itertools.htmlそれらをフィルタリングしなければならないかもしれません。 –

答えて

5

簡単なリスト内包:

>>> lst = [1, 2, 3, 4, 5] 
>>> [(a, b) for i, a in enumerate(lst) for b in lst[i+2:]] 
[(1, 3), (1, 4), (1, 5), (2, 4), (2, 5), (3, 5)] 
+0

小さな最適化: 'enumerate(lst [: - 2])'。 –

+0

@ivan_pozdeev Mmh、私はそれが好きではありません。そして私はそれが最適化だとは思わない。私はそれが悪いと思う*。はい、あなたは私の最後の2回の反復を防ぎますが、最初の[i + 2:]は空ですので、ほとんど何も保存しません。そしてそれは、リスト全体のもう1つのコピーを犠牲にして行われます。これには時間がかかり、全体的にメモリが必要です。 –

+0

これは 'k≒n'のためにより大きな役割を果たすでしょう。スライス時にコピーしないリストではなく、numpy配列の場合 –

3

モジュールを使用していないかなり慣用的な方法です。これは、ループを通るたびに使用されるため、他の実装よりも効率的です。

r = [1, 2, 3, 4, 5] 
c = [(r[i], r[j]) for i in range(len(r)-2) for j in range(i+2, len(r))] 
print(c) 

これは

[(1, 3), (1, 4), (1, 5), (2, 4), (2, 5), (3, 5)] 

を与え、それがインデックスではなく、値をループするので、それは、完全に慣用的ではなく、リスト内の位置ではなく値についてのあなたの制限はそれがかなり必要になります。リストではなくジェネレータを使用する場合は、外側のカッコをカッコで置き換えます。

+0

これは基本的に[@ StefanPochmanの解答](http:// stackoverflow。)の最適化です。com/questions/40438676/two-non-continuous-itemsの組み合わせ/ 40438842#40438842)、リストのコピーを避けることができます。あなたは 'xrange'を使ってスピードアップを増やすことができます。 'range'はCループよりもはるかに遅いので、実際には@ StefanPochmanの答えよりも_slower_で動作します。私のマシン上の1000のリストのために' 270ms'と '174ms'です。 –

1

リストから非連続番号との組み合わせに興味がある場合:

from itertools import combinations 

lst = [1, 2, 3, 4, 5] 
list(filter(lambda x: lst.index(x[1]) - lst.index(x[0]) > 1, combinations(lst,2))) 

[(1, 3), (1, 4), (1, 5), (2, 4), (2, 5), (3, 5)] 

これは、所定の組み合わせで2つの数の指標を比較し、そのインデックスの差が大きいことを確認します

私はそれが役に立ちそうです。

1

は、ここでの連続した要素を回避R長の組み合わせのための一般的なソリューションです。適切に短いリストのすべてのインデックスcombinationsを取得し、各組み合わせのインデックスを展開します。たとえばr = 3の場合、任意の組み合わせ(x、y、z)は使用インデックスx + 0、y + 1、z + 2に変わります。 R = 2

from itertools import combinations 

def non_consecutive_combinations(lst, r): 
    return [tuple(lst[j+i] for i, j in enumerate(combi)) 
      for combi in combinations(range(len(lst)-r+1), r)] 

デモ:R = 3

>>> non_consecutive_combinations([1, 2, 3, 4, 5], 2) 
[(1, 3), (1, 4), (1, 5), (2, 4), (2, 5), (3, 5)] 

デモ:

>>> non_consecutive_combinations([1, 2, 3, 4, 5, 6, 7], 3) 
[(1, 3, 5), (1, 3, 6), (1, 3, 7), (1, 4, 6), (1, 4, 7), (1, 5, 7), (2, 4, 6), (2, 4, 7), (2, 5, 7), (3, 5, 7)] 

だけペアの簡略化されたバージョン:

>>> [(lst[i], lst[j+1]) for i, j in combinations(range(len(lst)-1), 2)] 
[(1, 3), (1, 4), (1, 5), (2, 4), (2, 5), (3, 5)] 
+0

なぜdownvote?これに何か問題がありますか? –

関連する問題