student = [['benny', 12.09], ['harry', 40.03], ['jenny', 56.03], ['garry', 56.33]]
for items in student:
for _ in range(len(items)):
if items[1] not in allscores:
allscores.append(items[1])
print allscores
上面代码的输出是
[12.09, 40.03, 56.03, 56.33]
符合预期。
但是,如果我将2个for
循环转换为列表理解,
allscores = [items[1] for _ in range(len(items)) if items[1] not in allscores for items in student]
print allscores
我得到:
allscores = [items[1] for _ in range(len(items)) if items[1] not in allscores for items in student]
NameError: name 'items' is not defined
我的列表理解有什么问题?
答案 0 :(得分:3)
出现错误的原因是,循环的理解力与for循环的编写顺序相同。特别是
a = []
for y in z:
for x in y:
a.append(x)
可以改写为
a = [x for y in z for x in y]
不是
a = [x for x in y for y in z]
您可能正在考虑的语法是用于嵌套理解的:
a = [[x for x in y] for y in z]
但这会创建一个2D列表,这肯定不是您想要的2em列表。
现在要回答您的实际问题,让我们从items[1] for _ in range(len(items))
开始。您实际上是对列表中的每个元素检查items[1]
两次。可能已经尝试确保子列表包含两个元素,但是在显式索引元素1
时将其杀死。
现在您会认为可以将理解力截断
allscores = [items[1] for items in students if items[1] not in allscores]
但是你不能。请记住,在理解完成之前,allscores
是未定义的。将其预初始化为空列表也无济于事,因为在理解完成之前它将一直为空。
解决方案是使用set
。它比您每次使用in
中的if items[1] not in allscores
运算符尝试执行的线性查找要有效得多。它也可以与生成器表达式一起使用,而不是与列表理解一起使用,以避免存储不必要的元素:
allscores = set(items[1] for items in students)
请注意缺少方括号。如果您绝对需要列表,请
allscores = list(set(items[1] for items in students))