Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
对于具有复杂数据对象的多个列表,使用pythonic方法执行AND或NOT_Python_Python 3.x_Boolean Operations - Fatal编程技术网

对于具有复杂数据对象的多个列表,使用pythonic方法执行AND或NOT

对于具有复杂数据对象的多个列表,使用pythonic方法执行AND或NOT,python,python-3.x,boolean-operations,Python,Python 3.x,Boolean Operations,我有多个包含复杂对象的列表。我想对它们执行布尔运算和,或,而不是 和:结果列表将包含所有已用源列表中存在的所有对象。不应该有重复的 或:结果列表应包含所有使用的源列表中的所有对象。不应该有重复的 NOT:结果列表应仅包含源列表中不存在于NOT列表中的现有对象 #!/usr/bin/env python3 # -*- coding: utf-8 -*- # the "complex data" class Person: def __init__(self, name):

我有多个包含复杂对象的列表。我想对它们执行布尔运算而不是

:结果列表将包含所有已用源列表中存在的所有对象。不应该有重复的

:结果列表应包含所有使用的源列表中的所有对象。不应该有重复的

NOT:结果列表应仅包含源列表中不存在于NOT列表中的现有对象

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# the "complex data"
class Person:
    def __init__(self, name):
        # assume the 'name' as unique
        self.name = name

# create example data
mylistA = [Person('Anna'),
           Person('Bob'),
           Person('Jane'),
           Person('Alfred')]

mylistB = [Person('Simon'),
           Person('Anna'),
           Person('Doris'),
           Person('Bob')]

mylistC = [Person('Bob'),
           Person('Rosi'),
           Person('Becky'),
           Person('Anna')]

mylistD = [Person('Alfred'),
           Person('Bob'),
           Person('Chris'),
           Person('Susi')]

def doAND(some_lists):
    pass

def doOR(some_lists):
    pass

def doNOT(one_list, not_list):
    pass

# should result in 'Anna', 'Bob'
resultAND = doAND([mylistA, mylistB, mylistC])
print(resultAND)

# should result in 'Anna', 'Bob', 'Jane', 'Alfred', 'Simon', 'Doris', 'Rosi',
# 'Becky'
resultOR = doOR([mylistA, mylistB, mylistC])
print(resultOR)

# 'Anna'
resultNOT = doNOT(resultAND, mylistD)
print(resultNOT)
背景信息:真实场景中的“复杂对象”是sqlalchemy对象。在我这里的例子中,他们的“身份”不是主键。他们的“身份”是根据他们的成员组成的(简单的例子:“名字”、“姓氏”、“出生日期”)。

你应该使用,而不是列表。 这样可以避免重复,并以方便的方式提供所有操作:

a=[1,2,3,4,5]
b=[1,2,3]

a=set(a)
b=set(b)

# OR
a | b # [1,2,3,4,5]

# AND
a & b # [1,2,3]

# NOT
a - b # [4,5]
即使对于复杂的数据类型,也可以使用它。他们需要满足两个标准:

  • \uuuu eq\uuuu
    需要实施
  • \uuuu散列\uuuu
    需要实现
集合需要
\uuuu eq\uuuu
来查找重复项。但是,如果只实现
\uuuuuuuuuuueq\uuuuu
,则默认的
\uuuuuuuuuuuuu散列\uuuuu
实现将被删除

这是因为
\uuuuueq\uuuu
\uuuuhash\uuuuu
需要一致。 因此,您需要重新实现
\uuuuu散列\uuuuu

您使用内置的
hash()
函数实际上比使用hashlib的我的版本要好得多。所以我更新了。 令人惊讶的是,
\uuuuuuu散列
的实现没有提供
\uuuuu eq
的隐式实现,即使具有相同散列的对象必须相等是不变量。因此,需要实现
\uuuuuuueq\uuuuu
\uuuuuhash\uuuuuu
。这在以前版本的答案中是错误的

由于性能原因,可能需要再次实现
\uuuu eq\uuu
运算符。我不知道
hash()
函数的速度有多快,但如果集合变大,直接比较名称可能是一种有用的优化方法,而不是先对它们进行散列

class Person:
    def __init__(self, name):
        # assume the 'name' as unique
        self.name = name

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

    def __eq__(self, other):
        return self.name == other.name
        # return hash(self) == hash(other)

    def __repr__(self):
        return self.name


persons = [Person("a"), Person("b"), Person("a")]

print(persons)  # [a, b, a]

persons_set= set(persons)

print(persons_set) # [a, b]

感谢@criket_007给了我正确的提示。Python是如此简单!只需为complexe数据对象创建操作符。然后您可以将它们视为
set

这就是更新后的示例

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# the "complex data"
class Person:
    def __init__(self, name):
        # assume the 'name' as unique
        self.name = name
    def __str__(self):
        return self.name
    def __repr__(self):
        return '{}:{}'.format(id(self), self.__str__())
    def __hash__(self):
        return hash(self.name)

# create example data
mylistA = [Person('Anna'),
           Person('Bob'),
           Person('Jane'),
           Person('Alfred')]
sa = set(mylistA)

mylistB = [Person('Simon'),
           Person('Anna'),
           Person('Doris'),
           Person('Bob')]
sb = set(mylistB)

mylistC = [Person('Bob'),
           Person('Rosi'),
           Person('Becky'),
           Person('Anna')]
sc = set(mylistC)

mylistD = [Person('Alfred'),
           Person('Bob'),
           Person('Chris'),
           Person('Susi')]
sd = set(mylistD)

# should result in 'Anna', 'Bob'
resultAND = sa.intersection(sb, sc)
print('AND: {}\n'.format(resultAND))

# should result in 'Anna', 'Bob', 'Jane', 'Alfred', 'Simon', 'Doris', 'Rosi',
# 'Becky'
resultOR = sa.union(sb, sc)
print('OR: {}\n'.format(resultOR))

# 'Anna'
resultNOT = resultAND.difference(sd)
print('NOT: {}\n'.format(resultNOT))

你应该为你的“复杂数据”实现一个
\uuuuuu eq\uuuu
,这不符合我提出的“复杂数据对象”的问题。我认为这非常适合。如果需要避免重复,则应定义什么是重复。在python中,这是通过一个哈希函数来实现的。为什么?我需要还是不需要?我无法测试它。以及为什么没有在
\uuuuhash()\uuuuu
中使用
hash()
。您的解决方案的优点是什么?@Ihk请您描述一下为什么在这里实现了
\uuuu eq\uuu()
。@lhk请查看历史或时间戳。你的答案的第一个版本不符合我的问题。谢谢你的更新。谢谢你的提示,我更新了我的答案。