【问题标题】:List comprehensions splitting loop variable列表推导拆分循环变量
【发布时间】:2012-04-25 03:26:29
【问题描述】:

我正在尝试找出是否有一种方法可以将列表理解的每次迭代的值拆分一次,但在输出中使用两次。

作为我要解决的问题的一个例子,我有字符串:

a = "1;2;4\n3;4;5"

我想这样做:

>>> [(x.split(";")[1],x.split(";")[2]) for x in a.split("\n") if x.split(",")[1] != 5]
[('2', '4'), ('4', '5')]

无需运行 split 3 次。所以是这样的(这显然是无效的语法,但希望足以传达信息):

[(x[1],x[2]) for x.split(";") in a.split("\n") if x[1] != 5]

在这个问题中,我不是寻找奇特的方法来获取字符串的第 2 列和第 3 列。这只是提供具体示例的一种方式。我当然可以作为示例使用:

[x.split(";")[1:3] for x in a.split("\n")]

我想到的可能的解决方案:

  1. 不使用列表理解
  2. 保持原样
  3. 使用csv.DictReader、命名我的列以及StringIO 之类的名称为其提供输入。

这主要是一种可以使用的很好的模式,而不是特定的案例,因此很难回答“你为什么要这样做”或“这是为了什么”之类的问题

更新:阅读下面的解决方案后,我进行了一些速度测试。而且我在非常基本的测试中发现,提供的解决方案比上面的简单解决方案快 35%。

【问题讨论】:

    标签: python split list-comprehension


    【解决方案1】:

    您可以使用包含在生成器表达式周围的列表推导:

    [(x[1],x[2]) for x in (x.split(";") for x in a.split("\n")) if x[1] != 5]
    

    【讨论】:

      【解决方案2】:

      Python 3.8 开始,并引入assignment expressions (PEP 572):= 运算符),可以在列表解析中使用局部变量以避免调用两次相同的表达式:

      在我们的例子中,如果parts[1] 不等于5,我们可以将line.split(';') 的评估命名为变量parts,同时使用表达式的结果来过滤列表;从而重新使用parts 来生成映射值:

      # text = '1;2;4\n3;4;5'
      [(parts[1], parts[2]) for line in text.split('\n') if (parts := line.split(';'))[1] != 5]
      # [('2', '4'), ('4', '5')]
      

      【讨论】:

        猜你喜欢
        • 2014-04-02
        • 1970-01-01
        • 2017-04-19
        • 2013-03-09
        • 2017-07-31
        • 2016-03-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多