想在python列表中防止欺骗

时间:2017-06-29 21:52:24

标签: python

我正在创建一个列表列表,并希望防止欺骗。例如,我有:

mainlist = [[a,b],[c,d],[a,d]]

要添加的下一个项目(列表)是[b,a],它被视为[a,b]的副本。

更新

mainlist  = [[a,b],[c,d],[a,d]]   
swap = [b,a]   

for item in mainlist:
   if set(item) & set(swap):
     print "match was found", item
   else:
     mainlist.append(swap)

关于如何测试下一个要添加的项目是否已经在列表中的任何建议?

2 个答案:

答案 0 :(得分:3)

以下是使用frozensetset来检查重复项的方法。由于我正在调用一个适用于全局变量的函数,所以它有点难看。

def add_to_mainlist(new_list):
    if frozenset(new_list) not in dups:
        mainlist.append(new_list)

mainlist = [['a', 'b'],['c', 'd'],['a', 'd']] 

dups = set()

for l in mainlist:
    dups.add(frozenset(l))

print("Before:", mainlist)
add_to_mainlist(['a', 'b'])
print("After:", mainlist)

输出:

Before: [['a', 'b'], ['c', 'd'], ['a', 'd']]
After: [['a', 'b'], ['c', 'd'], ['a', 'd']]

显示新列表确实未添加到原始列表中。

这是一个更干净的版本,可以在一个函数内动态计算现有的set,该函数可以在本地执行所有操作:

def add_to_mainlist(mainlist, new_list):
    dups = set()
    for l in mainlist:
        dups.add(frozenset(l))

    if frozenset(new_list) not in dups:
        mainlist.append(new_list)

    return mainlist

mainlist = [['a', 'b'],['c', 'd'],['a', 'd']] 

print("Before:", mainlist)
mainlist = add_to_mainlist(mainlist, ['a', 'b']) # the assignment isn't needed, but done anyway :-)
print("After:", mainlist)

为什么现有代码不起作用?

这就是你正在做的事情:

...
for item in mainlist:
   if set(item) & set(swap):
     print "match was found", item
   else:
     mainlist.append(swap)

你正在交叉两套并检查结果的真实性。虽然这可能适用于0个交叉点,但即使其中一个元素很常见(例如,['a', 'b']['b', 'd']),您仍然会声明一个错误的匹配。

理想情况下,您需要检查结果集的长度,并确保其长度等于2:

dups = False 
for item in mainlist:
    if len(set(item) & set(swap)) == 2:
        dups = True
        break

if dups == False:
    mainlist.append(swap)

理想情况下,您还需要一个标记,以确保您没有找到重复项。您之前的代码会添加,而不会先检查所有项目。

答案 1 :(得分:1)

如果您的内部列表的顺序无关紧要,那么可以使用frozenset() s来完成此操作:

>>> mainlist = [['a', 'b'],['c', 'd'],['a', 'd']]   
>>> mainlist = [frozenset(sublist) for sublist in mainlist]
>>> 
>>> def add_to_list(lst, sublist):
...     if frozenset(sublist) not in lst:
...         lst.append(frozenset(sublist))
... 
>>> mainlist
[frozenset({'a', 'b'}), frozenset({'d', 'c'}), frozenset({'a', 'd'})]
>>> add_to_list(mainlist, ['b', 'a'])
>>> mainlist
[frozenset({'a', 'b'}), frozenset({'d', 'c'}), frozenset({'a', 'd'})]
>>> 

如果订单确实重要,您可以执行@Coldspeed建议的操作 - 从列表中构建set(),从要添加的列表构建frozenset(),并测试成员资格 - 或者您可以使用all()sorted()来测试要添加的列表是否等同于任何其他列表:

>>> def add_to_list(lst, sublist):
...     for l in lst:
...         if all(a == b for a, b in zip(sorted(sublist), sorted(l))):
...             return
...     lst.append(sublist)
... 
>>> mainlist
[['a', 'b'], ['c', 'd'], ['a', 'd']]
>>> add_to_list(mainlist, ['b', 'a'])
>>> mainlist
[['a', 'b'], ['c', 'd'], ['a', 'd']]
>>>