当有多个列表传递到函数中时,第一个打印系统就会工作。然而,当只传入一个列表时,我会得到错误"AttributeError:'int'对象没有属性'pop'"
此代码试图从列表中删除一个项目,以查看弹出的项目是否仍存在于其余列表中。
def check_row(p):
for e in p:
while e:
x = e.pop()
if x in e:
return False
return True
print check_row([[8,2,3,4,5],
[2,3,1,5,6],
[4,0,2,3,1]])
print check_row([1,2,3,4,5])
非常感谢。
您弹出的是元素中的项目,而不是外部列表。如果您的元素不是列表,那么不要试图将它们视为列表。
但是,不能在循环外部列表的同时从外部列表中删除项目,并且期望循环不会跳过项目。
如果您想查看一个项目是否在列表中出现不止一次,请比较列表的set()
的长度:
def check_row(row):
return len(row) == len(set(row))
这只适用于可散列值,而嵌套列表不是,但至少不会像您的代码那样更改列表
您仍然可以使用列表扫描,但至少可以使用list.index()
将搜索限制在当前位置之外的起始索引:
def check_row(row):
for i, elem in enumerate(row):
try:
row.index(elem, i + 1)
return False # dupe found
except ValueError:
pass # no dupe found
return True
但是,这假设您只想测试外部列表中的重复项。在同一代码中支持嵌套结构和平面结构,而不详细说明每种情况下会发生什么,这要复杂得多。
在单个(非嵌套)列表的情况下,对不是列表的元素(e
)调用.pop()
,因此可能没有.pop
方法。
这是因为e
是列表中的一个元素。在嵌套式中,e
是一个列表,而在第二个嵌套式中e
是一个整数。因此,e.pop
对于第二个无效。
你必须使它始终嵌套:
>>> print(check_row([[1, 2, 3, 4, 5]]))
True
这样,传递给check_row的值总是一个嵌套列表,即使它只有一个元素。
但就检查元素是否仍在其他列表中而言,我会首先将列表压平,然后检查列表中是否有重复的元素。
import collections
def flatten(l):
for el in l:
if isinstance(el, collections.Iterable) and not isinstance(el, str):
for sub in flatten(el):
yield sub
else:
yield el
def check_row(p):
flat = list(flatten(p))
return len(flat) == len(set(flat))
这样,check_row
将始终生成您想要的结果,忽略它是列表或嵌套列表的事实:)
希望这能有所帮助!
您的命名混淆了自己。您调用的check_row
函数实际上会检查行的列表,而不管名称如何,因此将其传递给一行会失败。事实上,你使用了毫无意义的一个字母的名字也无济于事。让我们重写得更清楚:
如果你想要一个检查单行的函数,
def check_rows(rows):
for row in rows:
while row:
element = row.pop()
if element in row:
return False
return True
现在应该更清楚它失败的原因了:您将一个row
作为rows
传递给它,所以for row in rows
得到的是元素而不是行,从那以后一切都会走下坡路。
您可能想要的是一个在单行上工作的check_row
函数,然后是在每行上调用check_row
的check_rows
:
def check_row(row):
while row:
element = row.pop()
if element in row:
return False
return True
def check_rows(rows):
for row in rows:
if not check_row(row):
return False
return True
但实际上,我不知道你为什么想要这个函数。它破坏性地修改行,删除第一个重复之前的每个元素。你为什么要那样?例如,Martijn Pieters的解决方案更简单、更高效,而且是无损的:
def check_row(row):
return len(set(row)) == len(row)
在我们讨论的时候,让我们使用all
函数,而不是check_rows
:的显式循环
def check_rows(rows):
return all(check_row(row) for row in rows)