Python 列表理解中的多个变量?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/40351085/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
multiple variables in list comprehension?
提问by Dave
I want to create a list of lists from a list of multi-field strings and wonder if it is possible to do so in a comprehension.
我想从多字段字符串列表中创建一个列表列表,并想知道是否可以在理解中这样做。
Input:
输入:
inputs = ["1, foo, bar", "2, tom, jerry"]
Desired output:
期望的输出:
[[1, "foo", "bar"], [2, "tom", "jerry"]]
Splitting the string in a comprehension is easy:
在推导式中拆分字符串很容易:
>>> [s.split(",") for s in inputs]
[['1', ' foo', ' bar'], ['2', ' tom', ' jerry']]
But I'm having trouble figuring out how to access the columns after the string has been split inside the comprehension, because it would seem to require a variable assignment. The following are not valid Python, but illustrate what I'm looking for:
但是我无法弄清楚如何在理解中拆分字符串后访问列,因为它似乎需要变量赋值。以下不是有效的 Python,但说明了我在寻找什么:
[[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]
Is there a way to assign variables inside a comprehension so that the output can be composed of functions of the variables? A loop is trivial, but generating a list by transforming inputs sure seems like a "comprehension-ish" task.
有没有办法在推导中分配变量,以便输出可以由变量的函数组成?循环是微不足道的,但通过转换输入来生成列表确实看起来像是一项“理解性”任务。
outputs = []
for s in inputs:
x,y,z = s.split(",")
outputs.append([int(x), y.strip(), z.strip()])
回答by kindall
You can do this with two for
clauses in your list comprehension. The first iterates over the items in the list. The second iterates over a single-item list containing the list derived from splitting the string (which is needed so we can unpack this into three separate variables).
您可以使用for
列表推导式中的两个子句来做到这一点。第一个迭代列表中的项目。第二个迭代包含从拆分字符串派生的列表的单项列表(这是必需的,因此我们可以将其解包为三个单独的变量)。
[[int(x), y.strip(), z.strip()] for s in inputs for (x, y, z) in [s.split(",")]]
The for
clauses go in a somewhat counterintuitive order, but it matches the way you'd write it as nested for
loops.
这些for
子句的顺序有点违反直觉,但它与您将其编写为嵌套for
循环的方式相匹配。
Jon Sharpe's use of a nested comprehension (generator expression, actually) is similar and probably clearer. The use of multiple for
clauses always seems confusing to me; mainly I wanted to see if I could make use of it here.
Jon Sharpe 对嵌套推导式(实际上是生成器表达式)的使用与此类似,而且可能更清晰。使用多个for
子句对我来说似乎总是令人困惑。主要是想看看这里能不能用上。
回答by Dave
Thanks for all the suggestions - it's great to see the variety of possible techniques, as well as a counterexample to the zen of Python's "There should be one — and preferably only one — obvious way to do it."
感谢所有的建议 - 很高兴看到各种可能的技术,以及 Python 禅宗的反例,“应该有一个 - 最好只有一个 - 明显的方法来做到这一点。”
All 4 solutions are equally beautiful, so it's a bit unfair to have to give the coveted green check to only one of them. I agree with the recommendations that #1 is the cleanest and best approach. #2 is also straightforward to understand, but having to use a lambda inside a comprehension seems a bit off. #3 is nice in creating an iterator with map but gets a tiny demerit for needing the extra step of iterating over it. #4 is cool for pointing out that nested for's are possible -- if I can remember that they go in "first, second" order instead of "inner, outer". Since #1 is not in the form of an answer, #4 gets the check for most surprising.
所有 4 个解决方案都同样漂亮,因此只将梦寐以求的绿色支票授予其中一个是有点不公平的。我同意 #1 是最干净和最好的方法的建议。#2 也很容易理解,但必须在推导式中使用 lambda 似乎有点不对劲。#3 在创建带有 map 的迭代器方面很好,但由于需要额外的迭代步骤而有一个小小的缺点。#4 很酷地指出嵌套 for 是可能的——如果我记得它们按“第一,第二”顺序而不是“内部,外部”进行。由于#1 不是答案的形式,#4 得到了最令人惊讶的检查。
Thanks again to all.
再次感谢大家。
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
Results:
结果:
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']]
回答by user2314737
You can use map with a list comprehension
您可以将地图与列表理解结合使用
def clean(x):
return [int(x[0]), x[1].strip(), x[2].strip()]
map(clean,[s.split(",") for s in inputs])
# Output: [[1, 'foo', 'bar'], [2, 'tom', 'jerry']]
with a lambda function:
使用 lambda 函数:
map(lambda x: [int(x[0]), x[1].strip(), x[2].strip()],[s.split(",") for s in inputs])
回答by yper
If you really want to do it in one line, you can do something like this, although it's not the clearest code (first line is the code, second line is the output).
如果你真的想在一行中完成,你可以这样做,虽然它不是最清晰的代码(第一行是代码,第二行是输出)。
>>> [(lambda x, y, z: [int(x), y.strip(), z.strip()])(*s.split(",")) for s in inputs]
[[1, 'foo', 'bar'], [2, 'tom', 'jerry']]
Or this.
或这个。
>>> [(lambda x: [int(x[0]), x[1].strip(), x[2].strip()])(s.split(",")) for s in inputs]
[[1, 'foo', 'bar'], [2, 'tom', 'jerry']
Edit: See jonrsharpe's comment for the best answer IMHO.
编辑:请参阅 jonrsharpe 的评论以获得最佳答案恕我直言。
回答by shaktimaan
Another possible solution
另一种可能的解决方案
>>> 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'