25

私は2つのリストを持っています

List1 = ['a','c','c']
List2 = ['x','b','a','x','c','y','c']

ここで、List1のすべての要素がList2にあるかどうかを調べたいと思います。この場合、すべてがあります。リストに繰り返し要素を含めることができるため、サブセット関数を使用できません。forループを使用して、List1の各アイテムの出現回数をカウントし、それがList2の出現回数以下であるかどうかを確認できます。これを行うためのより良い方法はありますか?

ありがとう。

4

6 に答える 6

39

発生回数が重要でない場合でも、その場でセットを作成することにより、サブセット機能を使用できます。

>>> list1 = ['a', 'c', 'c']
>>> list2 = ['x', 'b', 'a', 'x', 'c', 'y', 'c']
>>> set(list1).issubset(list2)
True

各要素が少なくとも最初のリストと同じ回数だけ2番目のリストに表示されるかどうかを確認する必要がある場合は、Counterタイプを使用して、独自のサブセット関係を定義できます。

>>> from collections import Counter
>>> def counterSubset(list1, list2):
        c1, c2 = Counter(list1), Counter(list2)
        for k, n in c1.items():
            if n > c2[k]:
                return False
        return True
   
>>> counterSubset(list1, list2)
True
>>> counterSubset(list1 + ['a'], list2)
False
>>> counterSubset(list1 + ['z'], list2)
False

すでにカウンターがある場合(とにかくデータを保存するための便利な代替手段になる可能性があります)、これを1行で記述することもできます。

>>> all(n <= c2[k] for k, n in c1.items())
True
于 2013-02-28T23:40:29.870 に答える
5

次の点に注意してください。

>>>listA = ['a', 'a', 'b','b','b','c']
>>>listB = ['b', 'a','a','b','c','d']
>>>all(item in listB for item in listA)
True

英語のように「all」行を読む場合、これは間違いではありませんが、listAには3番目の「b」がありますがlistBにはないため、誤解を招く可能性があります。

これにも同じ問題があります。

def list1InList2(list1, list2):
    for item in list1:
        if item not in list2:
            return False
    return True

ただのメモ。以下は機能しません。

>>>tupA = (1,2,3,4,5,6,7,8,9)
>>>tupB = (1,2,3,4,5,6,6,7,8,9)
>>>set(tupA) < set(TupB)
False

タプルをリストに変換しても、それでも機能しません。文字列が機能する理由はわかりませんが、intは機能しません。

動作しますが、要素の発生数を保持しないという同じ問題があります。

>>>set(tupA).issubset(set(tupB))
True

セットの使用は、複数回出現要素のマッチングのための包括的なソリューションではありません。

しかし、ここに、試行/例外なしでのshantanooの答えに対するワンライナーソリューション/適応があります:

all(True if sequenceA.count(item) <= sequenceB.count(item) else False for item in sequenceA)

三元条件演算子を使用してリスト内包をラップする組み込み関数。Pythonは素晴らしいです!「<=」は「==」であってはならないことに注意してください。

このソリューションでは、シーケンスAとBは、タプルとリスト、および「カウント」メソッドを使用したその他の「シーケンス」と入力できます。両方のシーケンスの要素は、ほとんどのタイプにすることができます。現在のようにdictsでこれを使用しないので、「iterable」の代わりに「sequence」を使用します。

于 2015-06-25T08:59:29.023 に答える
1

Counterと組み込みの交差法を使用したソリューション(-要素ごとの減算ではなく、適切なマルチセットの差であることに注意してください):

from collections import Counter

def is_subset(l1, l2):
    c1, c2 = Counter(l1), Counter(l2)
    return not c1 - c2

テスト:

>>> List1 = ['a','c','c']
>>> List2 = ['x','b','a','x','c','y','c']
>>> is_subset(List1, List2)
True
于 2018-05-04T17:56:50.957 に答える
1

リストに繰り返し要素を含めることができるため、サブセット関数を使用できません。

これが意味するのは、リストをセットではなくマルチセットとして扱いたいということです。Pythonでマルチセットを処理する通常の方法は、次のcollections.Counterとおりです。

ACounterは、ハッシュ可能なオブジェクトをカウントするためのdictサブクラスです。これは、要素がディクショナリキーとして格納され、それらのカウントがディクショナリ値として格納される順序付けられていないコレクションです。カウントは、ゼロまたは負のカウントを含む任意の整数値にすることができます。このCounterクラスは、他の言語のバッグやマルチセットに似ています。

また、pokeの回答のように、カウントをループして比較することでマルチセットのサブセット(で実装)を実装できますが、ループとテストでセットのサブセット(またはで実装)を実装できるのと同じように、これは不要ですが、不要です。Countersetfrozensetin

このCounter型は、多重集合に対して明白な方法で拡張されたすべての集合演算子をすでに実装しています。<1したがって、これらの演算子の観点からサブセットを記述でき、それは箱から出して両方setで機能Counterします。

(多重)集合の差がある場合:2

def is_subset(c1, c2):
    return not c1 - c2

または(マルチ)セット交差点を使用:

def is_subset(c1, c2):
    def c1 & c2 == c1

1.集合演算子を実装する場合、適切なサブセットとサブセットを実装Counterするだけではないのはなぜか疑問に思われるかもしれません。メールスレッドは見つかりませんが、これについては十分に議論されたと思います。答えは、「集合演算子」は、の初期バージョンで定義された特定の演算子の集合として定義されているということでした。 IIRC…)、便宜上含まれているすべての演算子ではありません。まったく同じ方法で、そのような名前付きメソッドがないのとまったく同じように、他のタイプに適しているという理由だけではありません。<<=collections.abc.SetsetCounterintersection&set

2.これは、Pythonのコレクションが空の場合は偽であり、そうでない場合は真であると予想されるという事実に依存します。これは組み込み型についてここboolに文書化されており、テストがフォールバックするという事実はここlenで説明されていますが、これは最終的には単なる慣例であるため、numpy配列のような「準コレクション」は正当な理由がある場合に違反する可能性があります。、などの「実際のコレクション」にも当てはまります。本当に心配な場合は、書くことができますが、これはPEP8の精神に反することに注意してください。CounterOrderedDictlen(c1 - c2) == 0

于 2018-05-04T18:27:15.473 に答える
0

List1のすべてのアイテムがList2にある場合、これはtrueを返します。

def list1InList2(list1, list2):
    for item in list1:
        if item not in list2:
            return False
    return True
于 2013-03-01T00:03:16.487 に答える
-1
def check_subset(list1, list2):
    try:
        [list2.remove(x) for x in list1]
        return 'all elements in list1 are in list2'
    except:
        return 'some elements in list1 are not in list2'
于 2013-03-05T20:54:04.963 に答える