【问题标题】:python list comprehension without in没有 in 的 python 列表理解
【发布时间】:2023-03-26 21:04:02
【问题描述】:

如果 flattend 只是一个字符串列表,例如

['There','is','only','passion','and','piece','is','a','lie','lie','lie']

然后在下面两行

c = Counter(flattened)
vocab = [x for x, count in c.items() if count>=2]

[x for x,...] 部分是什么意思?另外, count 不应该是元组类型,因为我认为它是一个计数器项?这部分count>=2 怎么工作?!

注意: 我从调试中了解到,第一行将列表转换为计数器,第二行删除出现少于两次的项目。但我无法真正解释语法

【问题讨论】:

标签: python list list-comprehension


【解决方案1】:

所以这里的语法有点混乱,但实际上c.items() 中的每个项目都是一个包含单词及其计数的元组。

更清晰的写法是:

vocab = [x for (x, count) in c.items() if x>=2]

但也可以这样做:

vocab = [x[0] for x in c.items() if x[1]>=2]

x 是一个元组。

查看c 的实际外观也会有所帮助。如果你打印 c,你会看到:

>>> print c
Counter({'lie': 3, 'is': 2, 'and': 1, 'a': 1, 'There': 1, 'only': 1, 'passion': 1, 'piece': 1})

c.items()

>>> print c.items()
[('and', 1), ('a', 1), ('lie', 3), ('is', 2), ('There', 1), ('only', 1), ('passion', 1), ('piece', 1)]

【讨论】:

  • 换句话说,这相当于[x for (x, count)...]
  • 是的,为了清晰起见,添加了更清晰的解包语法
  • @bereal:这不仅是等价的,而且是相同的;所有非空tuples 的定义属性是逗号的存在,而不是括号;仅当存在歧义(例如,带有函数调用括号)或优先级问题(包括其他集合文字中的tuples)时才需要括号。当它不是真正关于制作tuples(例如,多次返回、解包值)时,在不需要括号时包含括号被认为更具Pythonic。
  • @ShadowRanger 在某些方面,“等价”和“相同”这两个词是等价的(或相同的)。
【解决方案2】:

Counter 将返回一个类似字典的结构。所以你需要遍历键和值,键是 x,值是计数。如果我们仔细观察c.items()

c.items() #list of tuples with (key,value)

[('and', 1),
 ('a', 1),
 ('lie', 3),
 ('is', 2), # x->'is' ,count->2
 ('There', 1),
 ('only', 1),
 ('passion', 1),
 ('piece', 1)]

因此,如果您要为单个元组迭代此列表,则有两个组件:一个单词和相关的计数。对于计数,您正在检查 count>=2 如果是,则返回列表中为 x 的键

【讨论】:

  • 你提供的显示只是Python 2上的情况; Counter 不仅仅是“字典式”,它还是一个 dict 子类,在 Python 3 上,这意味着 .items() 返回一个 dict 视图(底层 dict 的实时视图,具有固定开销重要的是底层dict 的大小,它随dict 变化,而不是list(在Py2 上是键/值对的急切副本,随后不会随dict 变化是产生自)。碰巧的是,它们都迭代相同(假设 dict 没有在迭代中发生突变),如果没有包装在 list() 中,您将看不到 list
【解决方案3】:

[x for x, ...] 只是在迭代某个数组时使用x 作为变量...

x, count 捕获作为来自c.items() 的迭代值的两项。

如果您要打印以下结果:for _ in c.items(): print(_),那将打印出像 (x, count) 这样的元组列表。

[x for x, count in c.items() if count > 2] 只是将x 保留在数组中,同时使用count 可迭代作为过滤器。

【讨论】:

    【解决方案4】:

    让我们把它分成几行:

    vocab = [           # line0
             x          # line1
             for        # line2
             x, count   # line3
             in
             c.items()
             if
             count>=2]  # line7
    

    c.items() 中的每个 tuple 都由一个键 x(被计数的东西)和一个 count(该键被看到的次数)组成。

    在每个循环中,您可以想象下一个tuple 被拉出,然后被解包,这样就不需要使用索引01 的单个值,您可以直接按名称引用它们; anontuple[0] 变为 xanontuple[1] 变为 count

    count>=2 行然后过滤结果;如果count小于2,我们停止处理这个项目,拉下一个。

    最左边的x是要生产的物品;当过滤检查通过时,我们将相应的x 推入未修改的list

    转换为常规循环,它看起来像这样(与 listcomp 行匹配的行):

    vocab = []                  # line0
    for x, count in c.items():  # lines 2-5
        if count >= 2:          # lines 6-7
            vocab.append(x)     # line1
    

    如果拆包让您感到困惑,您可以将其想象为:

    vocab = []              # line0
    for item in c.items():  # lines 2, 4 and 5
        x = item[0]         # line3
        count = item[1]     # line3
        if count >= 2:      # line 6-7
            vocab.append(x) # line1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-02
      • 1970-01-01
      • 1970-01-01
      • 2017-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多