4

2つのリストのいずれにも存在しないオブジェクトがあるかどうかのチェックに依存するモジュールに取り組んでいます。実装はPythonで行われることになっています。

簡略化されたオブジェクトdefについて考えてみます。

class Foo(object):

  def __init__(self, attr_one=None, attr_two=None):
    self.attr_one = attr_one
    self.attr_two = attr_two

  def __eq__(self, other):
    return self.attr_one == other.attr_one and self.attr_two == other.attr_two

次のように、クラスFooの複数のインスタンスをカプセル化できる2つの別個のリストがあります。

list1 = [Foo('abc', 2), Foo('bcd', 3), Foo('cde', 4)]
list2 = [Foo('abc', 2), Foo('bcd', 4), Foo('efg', 5)]

attr_oneに基づいて、一方のリストに存在し、もう一方のリストには存在しないオブジェクトを把握する必要があります。この場合、最初のリストに存在し、2番目のリストにないアイテムの望ましい出力を以下に示します。

`['Foo('bcd', 3), Foo('cde', 4)]` 

同様に、リスト2には存在するが、リスト1には存在しないアイテム

 [Foo('bcd', 4), Foo('efg', 5)]

attr_oneのベースにも一致する方法があるかどうか知りたいです。

  List 1                 List 2        
  Foo('bcd', 3)          Foo('bcd', 4)
  Foo('cde', 4)          None
  None                   Foo('efg', 5)
4

3 に答える 3

8

すでに__eq__メソッドが定義されているため、リスト内包表記を使用して、いずれかのリスト内のオブジェクトの一意性を見つけることができます。

print [obj for obj in list1 if obj not in list2]
于 2013-02-11T07:44:00.713 に答える
4

リストをすばやく比較して、一方には存在するが他方には存在しない要素を判断する良い方法は、元のリストからセットを作成し、2 つのセットの違いを取ることです。リストをセットにするには、リストに含まれるオブジェクトがhashableである必要があるため、オブジェクトの新しい__hash__()メソッドを定義する必要があります。Foo

def __hash__(self):
    return hash((self.attr_one,self.attr_two))

attr_oneとがハッシュ可能な型である限り、タプルはハッシュ可能であるためattr_two、この実装はかなり堅固であることに注意してください。

ここで、一方のリストに存在し、もう一方のリストに存在しない要素を特定するには、次のようにします。

set1 = set(list1)
set2 = set(list2)
missing_from_1 = set2 - set1
missing_from_2 = set1 - set2

1 つの属性のみに基づいてこれを行うには、属性自体のみを使用してセットを作成できます。

set1 = set([i.attr_one for i in list1])

もちろん、これは、実際のオブジェクトattr_oneを提供するのではなく、一方のリストに存在する値のみを示し、他方のリストには存在しない結果になることを意味します。Fooただし、「欠落している」セットがあれば、オブジェクト自体は簡単に見つけることができます。

missing_Foos = set()
for attr in missing_from_2:
    for i in list1:
        if i.attr_one == attr:
            missing_Foos.add(i)

ただし、非常に長いリストがある場合、これは計算コストがかなり高くなる可能性があります。

編集: セットの使用は、非常に大きなリストがあり、セット操作の計算効率を利用する必要がある場合にのみ本当に役立ちます。それ以外の場合は、他の回答で提案されているように、単にリスト内包表記を使用する方が簡単な場合があります。

于 2013-02-11T07:43:05.443 に答える
1

私がこれを行うには2つの方法があります-を使用するかsets、またはでfilter

class Foo(object):

    def __init__(self, attr_one=None, attr_two=None):
        self.attr_one = attr_one
        self.attr_two = attr_two

    def __eq__(self, other):
        return self.attr_one == other.attr_one and self.attr_two == other.attr_two

    def __hash__(self):
        return hash(self.attr_one)

    def __repr__(self):
        return "<Foo {} {}>".format(self.attr_one, self.attr_two)

def main():
    a = Foo('test', 1)
    b = Foo('test', 1)

    list1 = [Foo('abc', 2), Foo('bcd', 3), Foo('cde', 4)]
    list2 = [Foo('abc', 2), Foo('bcd', 4), Foo('efg', 5)]

    # With sets
    list1set = set(list1)
    list2set = set(list2)

    print list1set.intersection(list2set) 
    # Returns set([<Foo abc 2>])

    # With filter
    list2attr_one = [l.attr_one for l in list2]
    print filter(lambda x: x.attr_one in list2attr_one, list1)
    # Returns [<Foo abc 2>, <Foo bcd 3>]
于 2013-02-11T07:49:47.213 に答える