回答:
TL; DR:
ソリューション(1)
import numpy as np
main_list = np.setdiff1d(list_2,list_1)
# yields the elements in `list_2` that are NOT in `list_1`
ソリューション(2) ソートされたリストが必要です
def setdiff_sorted(array1,array2,assume_unique=False):
ans = np.setdiff1d(array1,array2,assume_unique).tolist()
if assume_unique:
return sorted(ans)
return ans
main_list = setdiff_sorted(list_2,list_1)
説明:
(1)あなたはnumpyののを使用することができますsetdiff1d
(array1
、array2
、assume_unique
= False
)。
assume_unique
配列がすでに一意であるかどうかをユーザーに尋ねます。
の場合False
、一意の要素が最初に決定されます。
の場合True
、関数は要素がすでに一意であると想定し、関数は一意の要素の決定をスキップします。
この利回りユニークな値array1
それはありませんでarray2
。assume_unique
でFalse
、デフォルトで。
(Chinny84の応答に基づく)一意の要素に関心がある場合は、単に(ここで=>デフォルト値)を使用します。assume_unique=False
import numpy as np
list_1 = ["a", "b", "c", "d", "e"]
list_2 = ["a", "f", "c", "m"]
main_list = np.setdiff1d(list_2,list_1)
# yields the elements in `list_2` that are NOT in `list_1`
(2)
回答をソートしたい人のために、カスタム関数を作成しました:
import numpy as np
def setdiff_sorted(array1,array2,assume_unique=False):
ans = np.setdiff1d(array1,array2,assume_unique).tolist()
if assume_unique:
return sorted(ans)
return ans
答えを得るには、以下を実行します。
main_list = setdiff_sorted(list_2,list_1)
サイドノート:
(a)ソリューション2(カスタム関数setdiff_sorted
)はリストを返します(ソリューション1の配列と比較)。
(b)要素が一意であるかどうかわからない場合はsetdiff1d
、ソリューションAとBの両方でNumPyのデフォルト設定を使用してください。複雑さの例は何ですか?注(c)を参照してください。
(c)2つのリストのいずれかが一意でない場合、状況は異なります。
一意ではないと
言いlist_2
ます:list2 = ["a", "f", "c", "m", "m"]
。現状維持list1
:利回りlist_1 = ["a", "b", "c", "d", "e"]
のデフォルト値を設定します(両方のソリューションで)。ただし、設定すると、両方のソリューションが提供します。どうして?これは、要素が一意であるとユーザーが想定したためです。したがって、それは維持する方が良いですassume_unique
["f", "m"]
assume_unique=True
["f", "m", "m"]
assume_unique
デフォルト値に。両方の回答がソートされていることに注意してください。
セットを使用できます。
main_list = list(set(list_2) - set(list_1))
出力:
>>> list_1=["a", "b", "c", "d", "e"]
>>> list_2=["a", "f", "c", "m"]
>>> set(list_2) - set(list_1)
set(['m', 'f'])
>>> list(set(list_2) - set(list_1))
['m', 'f']
@JonClementsのコメントによると、こちらはよりきれいなバージョンです。
>>> list_1=["a", "b", "c", "d", "e"]
>>> list_2=["a", "f", "c", "m"]
>>> list(set(list_2).difference(list_1))
['m', 'f']
unique
要素のみを考慮している場合は適切ですがm's
、たとえば複数の要素がある場合、これは取得されません。
list(set(list_2).difference(list_1))
これを明示的なset
変換を回避するように書くことができます...
main_list = [item for item in list_2 if item not in list_1]
出力:
>>> list_1 = ["a", "b", "c", "d", "e"]
>>> list_2 = ["a", "f", "c", "m"]
>>>
>>> main_list = [item for item in list_2 if item not in list_1]
>>> main_list
['f', 'm']
編集:
以下のコメントで述べたように、大きなリストでは、上記は理想的なソリューションではありません。その場合、より良いオプションは最初のものに変換するlist_1
ことset
です:
set_1 = set(list_1) # this reduces the lookup time from O(n) to O(1)
main_list = [item for item in list_2 if item not in set_1]
list_1
、あなたはにpreconvertにしたいと思いますset
/ frozenset
例えば、set_1 = frozenset(list_1)
その後、main_list = [item for item in list_2 if item not in set_1]
からチェック時間を削減する、O(n)
項目ごとに(およそ)へO(1)
。
enumerate()
:[index for (index, item) in enumerate(list_2) if item not in list_1]
あなたが唯一必要とワンライナー溶液(輸入を無視して)したい場合はO(max(n, m))
長さの入力のための作業n
とm
、ないO(n * m)
仕事を、あなたがそうすることができるモジュール。itertools
from itertools import filterfalse
main_list = list(filterfalse(set(list_1).__contains__, list_2))
これは、関数関数が構築時にコールバック関数を利用することを利用して、コールバックを一度作成し、どこかに保存する必要なく(すべての要素filterfalse
に内部的に保存するため)再利用できるようにします。リスト内包表記とジェネレータ式はこれを行うことができますが、醜いです。†
これは、1行で同じ結果になります。
main_list = [x for x in list_2 if x not in list_1]
の速度で:
set_1 = set(list_1)
main_list = [x for x in list_2 if x not in set_1]
もちろん、比較が位置的であることが意図されている場合は、次のようになります。
list_1 = [1, 2, 3]
list_2 = [2, 3, 4]
生成する必要があります:
main_list = [2, 3, 4]
(の値はlist_2
の同じインデックスで一致するためlist_1
)一時的なsやs を含まないPatrickの答えに間違いなく行く必要があります(sがおおよその場合でも、単純な等式チェックよりもチェックごとの「定数」係数が高くなります) )そして、他のどの答えよりも少ない作業を含み、問題が位置に敏感である場合、一致する要素が不一致のオフセットに表示されるときの唯一の正しい解決策です。list
set
set
O(1)
O(min(n, m))
†:ワンライナーと同じようにリスト内包で同じことを行う方法は、ネストされたループを悪用して、「最も外側の」ループで値を作成およびキャッシュすることです。例:
main_list = [x for set_1 in (set(list_1),) for x in list_2 if x not in set_1]
これはまた、Python 3でパフォーマンスのマイナーな利点を提供します(現在set_1
、各チェックのネストされたスコープから検索されるのではなく、内包コードでローカルにスコープされているためです。Python2では、Python 2はクロージャーを使用しないため、重要ではありません。内包表記をリストします。それらは、使用されているのと同じスコープで動作します)。
main_list=[]
list_1=["a", "b", "c", "d", "e"]
list_2=["a", "f", "c", "m"]
for i in list_2:
if i not in list_1:
main_list.append(i)
print(main_list)
出力:
['f', 'm']
list_1
が大きい場合はサイズが大きく、list_2
自明ではないサイズになると遅くなります。前もって/に変換すると、containsのチェックをで行うことができ、(を作成するために作業を行うため、技術的には)の長さで全体の作業が行われます。len(list_2)
O(n)
list_1
O(n * m)
n
m
list_2
list_1
list_1
set
frozenset
O(1)
O(n)
list_2
O(max(n, m))
O(m)
set
私は考えzip
リストは一緒要素により、これらの要素を比較します。
main_list = [b for a, b in zip(list1, list2) if a!= b]
list
のsを1回の安価なパスで1つの新しいパスlist
が作成され、追加の一時的なものがないためです。 、高価な封じ込めチェックなどは
私は2つの方法を使用しましたが、1つの方法が他の方法よりも有用であることに気付きました。これが私の答えです:
私の入力データ:
crkmod_mpp = ['M13','M18','M19','M24']
testmod_mpp = ['M13','M14','M15','M16','M17','M18','M19','M20','M21','M22','M23','M24']
方法1:np.setdiff1d
位置が保持されるため、他の方法よりもこの方法が好きです
test= list(np.setdiff1d(testmod_mpp,crkmod_mpp))
print(test)
['M15', 'M16', 'M22', 'M23', 'M20', 'M14', 'M17', 'M21']
方法2:方法1と同じ答えを出しますが、順序を乱します
test = list(set(testmod_mpp).difference(set(crkmod_mpp)))
print(test)
['POA23', 'POA15', 'POA17', 'POA16', 'POA22', 'POA18', 'POA24', 'POA21']
Method1 np.setdiff1d
は私の要件を完全に満たしています。情報のためのこの答え。
発生回数を考慮する必要がある場合は、おそらく次のようなものを使用する必要がありますcollections.Counter
。
list_1=["a", "b", "c", "d", "e"]
list_2=["a", "f", "c", "m"]
from collections import Counter
cnt1 = Counter(list_1)
cnt2 = Counter(list_2)
final = [key for key, counts in cnt2.items() if cnt1.get(key, 0) != counts]
>>> final
['f', 'm']
約束したように、これは異なる数の発生を「差異」として処理することもできます。
list_1=["a", "b", "c", "d", "e", 'a']
cnt1 = Counter(list_1)
cnt2 = Counter(list_2)
final = [key for key, counts in cnt2.items() if cnt1.get(key, 0) != counts]
>>> final
['a', 'f', 'm']
list_2
どこにも表示されlist_1
ない要素、またはlist_2
同じインデックスに存在しない要素を探していlist_1
ますか?