【问题标题】:Why do nested comprehensions don't work as expected? [duplicate]为什么嵌套推导不能按预期工作? [复制]
【发布时间】:2022-01-12 01:34:15
【问题描述】:

我想读取一个以逗号分隔的值的文件,并计算这些值的频率(在 0 .. 8 的范围内):

1,1,1,1,1,2,0,0,0,0,0,1,2,3,4,7,7,8,0,0,0

此代码有效:

with open("data.txt") as file:
    l =  [int(s) for s in file.readline().strip().split(",")]
    a1 = [l.count(i) for i in range(9)]
print(a1)

首先我读取文件,用逗号分割它,并将输入的字符串转换为整数,收集列表l 中的所有内容。但是,将相同的两个作业合并为一个会中断:

with open("data.txt") as file:
    a2 = [[int(s) for s in file.readline().strip().split(",")].count(i) for i in range(9)]
print(a2)
$ python -i aa.py # both snippets from above in one file
[0, 162, 36, 27, 47, 28, 0, 0, 0]
Traceback (most recent call last):
  File "aa.py", line 7, in <module>
    a2 = [([int(s) for s in file.readline().strip().split(",")].count(i)) for i in range(9)]
  File "aa.py", line 7, in <listcomp>
    a2 = [([int(s) for s in file.readline().strip().split(",")].count(i)) for i in range(9)]
  File "aa.py", line 7, in <listcomp>
    a2 = [([int(s) for s in file.readline().strip().split(",")].count(i)) for i in range(9)]
ValueError: invalid literal for int() with base 10: ''

P.S.:我知道我可能会使用 collections.Counter 并且 strip() 在这里可能不是必需的,但这并不能解释为什么我不能将这两个作业合二为一。

【问题讨论】:

  • 内部理解被评估了 9 次,但在第一次评估时耗尽了文件对象。

标签: python python-3.x list-comprehension


【解决方案1】:

列表推导版本等价于:

with open("data.txt") as file:
    a2 = []
    for i in range(9):
        a2.append([int(s) for s in file.readline().strip().split(",")].count(i))
print(a2)

所以它执行剩余的列表理解 9 次。但是文件流位置并没有在它们之间重置,因此每次执行列表推导的结果可能不同。

根据“一个语句”的理解,您可以使其与立即执行的 lambda 函数一起工作:

with open("data.txt") as file:
    a1 = (lamda l: [l.count(i) for i in range(9)])([int(s) for s in file.readline().strip().split(",")])

这仅应被视为一种理论上的可能性:这种编码模式应该被拒绝,因为它会降低代码的可读性并且不会带来效率方面的好处。

【讨论】:

  • 啊,我明白了。但是解决方案呢?
  • 我以为你有解决方案?为什么要更改有效的东西?
  • 解决方案是什么?您只想创建一次列表;为什么要尝试将它与迭代该列表 9 次的代码结合起来?
  • 问题是关于嵌套两个理解,而不是读取实际频率。那只是解释问题的一个例子。我的意思是,一个可能的答案是“写更短的语句”,但我仍然想知道这是否可能以及如何可能。
  • 替换 2 个未嵌套但一个在另一个开始之前完成的迭代,不应替换为 2 个嵌套迭代,因为这只是一种不同的算法,并且通常不会产生相同的结果。这就像加法和乘法之间的区别......为什么你想要不同的算法?
猜你喜欢
  • 1970-01-01
  • 2021-02-24
  • 1970-01-01
  • 1970-01-01
  • 2021-05-30
  • 2020-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多