web-dev-qa-db-ja.com

リスト内の一般的でない要素を見つける

式を自動的に因数分解できるコードを記述しようとしています。たとえば、2つのリスト[1,2,3,4]と[2,3,5]がある場合、コードは2つのリスト[2,3]の共通要素を見つけて、残りの要素は新しいリストにまとめられ、[1,4,5]になります。

この投稿から: リストの交差点を見つける方法? 共通の要素は

set([1,2,3,4]&set([2,3,5]). 

私の例では[1,4]と[5]のように、各リストから一般的でない要素を取得する簡単な方法はありますか?

先に進んでforループを実行できます。

lists = [[1,2,3,4],[2,3,5]]
conCommon = []
common = [2,3]
for elem in lists:
    for elem in eachList:
    if elem not in common:
        nonCommon += elem

しかし、これは冗長で非効率的です。 Pythonはそれを行うことができる便利な機能を提供しますか?事前に感謝します!!

25
turtlesoup

setsには対称差分演算子を使用します(別名XOR演算子):

>>> set([1,2,3]) ^ set([3,4,5])
set([1, 2, 4, 5])
48
Amber

交差点の概念を使用して、この種の問題に対処できます。

b1 = [1,2,3,4,5,9,11,15]
b2 = [4,5,6,7,8]
set(b1).intersection(b2)
Out[22]: {4, 5}

このコードを使用することの最大の利点は、大きなデータでも非常に高速に機能することです。このロジックを使用すると、607139のb1と296029の要素のb2があり、2.9秒で結果が得られます。

12

古い質問ですが、pythonには、探しているものを正確に提供する組み込み関数.difference()があります。

[〜#〜] example [〜#〜]

_list_one = [1,2,3,4]
list_two = [2,3,5]

one_not_two = set(list_one).difference(list_two)
# set([1, 4])

two_not_one = set(list_two).difference(list_one)
# set([5])
_

これは次のように書くこともできます。

_one_not_two = set(list_one) - set(list_two)
_

タイミング

私は両方でいくつかのタイミングテストを実行し、.difference()にはわずかなエッジがあり、10から15%の調整が行われているようですが、各メソッドは1Mアイテム(500の間のランダムな整数100,000)、したがって、あなたが非常に時間に敏感でない限り、おそらく重要ではありません。

その他の注意

OPは2つの個別のリスト(またはセット)を提供するソリューションを探しているようです。1つ目は2つ目のリストではなく、2つ目ではないアイテムを含むリストです。以前の回答のほとんどは、すべてのアイテムを含む単一のリストまたはセットを返します。

また、最初のリストで重複する可能性のあるアイテムを複数回カウントするか、1回だけカウントするかについても疑問があります。

OPが重複を維持したい場合、リスト内包表記を使用できます。例:

_one_not_two = [ x for x in list_one if x not in list_two ]
two_not_one = [ x for x in list_two if x not in list_one ]
_

...これは元の質問で提起されたものとほぼ同じ解決策であり、少しだけきれいです。この方法は元のリストからの複製を維持しますが、かなり大きい(複数桁のように)大きいデータセットに対しては遅くなります。

1
elPastor

.__xor__属性メソッドを使用できます。

set([1,2,3,4]).__xor__(set([2,3,5]))

または

a = set([1,2,3,4])
b = set([2,3,5])
a.__xor__(b)
0
SuperNova