对于具有复杂数据对象的多个列表,使用pythonic方法执行AND或NOT
我有多个包含复杂对象的列表。我想对它们执行布尔运算和,或,而不是 和:结果列表将包含所有已用源列表中存在的所有对象。不应该有重复的 或:结果列表应包含所有使用的源列表中的所有对象。不应该有重复的 NOT:结果列表应仅包含源列表中不存在于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):
#!/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请查看历史或时间戳。你的答案的第一个版本不符合我的问题。谢谢你的更新。谢谢你的提示,我更新了我的答案。