列表理解中的多个变量?

时间:2016-10-31 21:46:25

标签: python list-comprehension

我想从多字段字符串列表中创建一个列表列表,并想知道是否可以在理解中这样做。

输入:

aList

期望的输出:

inputs = ["1, foo, bar", "2, tom, jerry"]

在理解中拆分字符串很简单:

[[1, "foo", "bar"], [2, "tom", "jerry"]]

但是我很难弄清楚在理解之后字符串被拆分后如何访问列,​​因为它似乎需要一个变量赋值。以下是无效的Python,但说明了我正在寻找的内容:

>>> [s.split(",") for s in inputs]
[['1', ' foo', ' bar'], ['2', ' tom', ' jerry']]

有没有办法在理解中分配变量,以便输出可以由变量的函数组成?一个循环是微不足道的,但通过转换输入生成一个列表肯定看起来像是一个“理解是什么”的任务。

[[int(x), y.strip(), z.strip() for x,y,z = s.split(",")] for s in inputs]
    or
[[int(v[0]), v[1].strip(), v[2].strip() for v = s.split(",")] for s in inputs]

5 个答案:

答案 0 :(得分:9)

您可以使用列表解析中的两个for子句执行此操作。第一个迭代列表中的项目。第二个迭代单个项目列表,其中包含从拆分字符串派生的列表(这是必需的,因此我们可以将其解压缩为三个单独的变量)。

[[int(x), y.strip(), z.strip()] for s in inputs for (x, y, z) in [s.split(",")]]

for子句的顺序有点违反直觉,但它与您将其编写为嵌套for循环的方式相匹配。

Jon Sharpe使用嵌套理解(实际上是生成器表达式)是类似的,可能更清晰。使用多个for条款似乎总是令我感到困惑;主要是我想知道我是否可以在这里使用它。

答案 1 :(得分:2)

您可以使用带有列表推导的地图

New

使用lambda函数:

False

答案 2 :(得分:2)

感谢所有的建议 - 很高兴看到各种可能的技术,以及Python的“应该有一个 - 最好只有一个 - 显而易见的方法”的反例。

所有4种解决方案都同样美观,所以不得不将令人垂涎的绿色支票给予其中一种,这有点不公平。我同意#1是最干净,最好的方法的建议。 #2也很容易理解,但在理解中不得不使用lambda似乎有点过时了。 #3非常适合用map创建迭代器,但是因为需要额外的迭代步骤而得到一个很小的缺点。 #4很酷,指出嵌套的是可能的 - 如果我记得他们进入“第一,第二”顺序而不是“内部,外部”。由于#1不是答案的形式,#4得到最令人惊讶的检查。

再次感谢所有人。

inputs = ["1, foo, bar", "2,tom,  jerry"]

outputs1 = [[int(x), y.strip(), z.strip()] for x,y,z in (s.split(',') for s in inputs)]
print("1:", outputs1)       # jonrsharpe

outputs2 = [(lambda x, y, z: [int(x), y.strip(), z.strip()])(*s.split(",")) for s in inputs]
print("2:", outputs2)       # yper

outputs3 = [z for z in map(lambda x: [int(x[0]), x[1].strip(), x[2].strip()],[s.split(",") for s in inputs])]
print("3:", outputs3)       # user2314737

outputs4 = [[int(x), y.strip(), z.strip()] for s in inputs for (x, y, z) in [s.split(",")]]
print("4:", outputs4)       # kindall

结果:

1: [[1, 'foo', 'bar'], [2, 'tom', 'jerry']]
2: [[1, 'foo', 'bar'], [2, 'tom', 'jerry']]
3: [[1, 'foo', 'bar'], [2, 'tom', 'jerry']]
4: [[1, 'foo', 'bar'], [2, 'tom', 'jerry']]

答案 3 :(得分:1)

如果你真的想在一行中做,你可以这样做,虽然它不是最清晰的代码(第一行是代码,第二行是输出)。

>>> [(lambda x, y, z: [int(x), y.strip(), z.strip()])(*s.split(",")) for s in inputs]
[[1, 'foo', 'bar'], [2, 'tom', 'jerry']]

或者这个。

>>> [(lambda x: [int(x[0]), x[1].strip(), x[2].strip()])(s.split(",")) for s in inputs]
[[1, 'foo', 'bar'], [2, 'tom', 'jerry']

编辑: 请参阅jonrsharpe的评论以获得最佳答案恕我直言。

答案 4 :(得分:0)

另一种可能的解决方案

>>> inputs = [[1, "foo", "bar"], [2, "tom", "jerry"]]
>>> list_of_dicts = [{"var{}".format(k): v for k, v in enumerate(s, start=1)} for s in inputs]
>>> list_of_dicts[0]['var1']
1
>>> list_of_dicts[0]['var2']
'foo'