列表解析拆分循环变量(List comprehensions splitting loop vari

2019-06-23 23:07发布

我试图找出是否有分割列表理解的每次迭代的价值只有一次,但在输出使用两次的方式。

正如我试图解决的问题的一个例子,我有字符串:

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')]

无需运行分裂三次。 因此,像这样(这显然是无效的语法,但希望是足以传达出消息):

[(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%找到。

Answer 1:

你可以使用列表理解周围生成器表达式包裹:

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


Answer 2:

开始Python 3.8 ,并引进了赋值表达式(PEP 572) ( :=运算符),这是可能的,以避免调用两次相同的表达式中使用列表理解中的一个局部变量:

在我们的情况下,我们可以命名的评价line.split(';')作为可变parts在使用表达式的结果来过滤列表如果parts[1]不等于5 ; 从而重复使用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')]


文章来源: List comprehensions splitting loop variable