为了账号安全,请及时绑定邮箱和手机立即绑定

将 for 循环转换为列表理解会产生不正确的结果

将 for 循环转换为列表理解会产生不正确的结果

叮当猫咪 2021-06-07 05:37:00
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我的列表理解有什么问题?
查看完整描述

1 回答

?
长风秋雁

TA贡献1757条经验 获得超7个赞

出现错误的原因是像这样的双重理解中的循环是按照与 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 列表,这绝对不是您在这里想要的。


现在要回答您的实际问题,让我们从items[1] for _ in range(len(items)). 您实际上是items[1]在为列表中的每个元素检查两次。可能已经尝试确保子列表有两个元素,但是当您显式索引 element 时您将其杀死1。


现在你会认为你可以将你的理解截断为


allscores = [items[1] for items in students if items[1] not in allscores]

但你不能。请记住,在理解完成之前,allscores是未定义的。将其预初始化为空列表也无济于事,因为在理解完成之前它将保持为空。


解决方案是使用set. 它比您每次尝试使用inin 中的运算符进行的线性查找要高效得多if items[1] not in allscores。它还可以与生成器表达式而不是列表推导式一起使用,以避免存储不必要的元素:


allscores = set(items[1] for items in students)

请注意缺少周围的方括号。如果您绝对需要列表,请执行


allscores = list(set(items[1] for items in students))


查看完整回答
反对 回复 2021-06-09
  • 1 回答
  • 0 关注
  • 120 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信