带有if语句的嵌套列表推导式

9
我正在尝试理解嵌套列表推导式,并阅读了这里的优秀解释。
我遇到的问题是,在我的内部循环中有一个if子句,而且我无法看到如何将其应用于func()步骤,因为当我从嵌套循环转换为列表推导式时,我失去了来自enumerate()的计数器。
nested_list = [[{'a': 1, 'b': 2}, {'c': 3, 'd': 4}], [{'a': 5, 'b': 6}, {'c': 7, 'd': 8}]]
new_list = []
for c, x in enumerate(nested_list):
    for d, y in enumerate(x):
        if d == 1:
            new_list.append(y)
print(new_list)
[{'c': 3, 'd': 4}, {'c': 7, 'd': 8}]

嵌套列表推导式可能看起来像这样:
new_list = [if ??? y
               for x in nested_list
                   for y in x]

...但是我看不到/想不到如何在嵌套的列表推导式中获取子句,因为没有计数器。

有没有办法实现这个功能,或者我应该坚持使用嵌套循环的方法?


列表推导式使用相同的嵌套顺序,从左到右。将if移到相同的位置,不要将其放在值表达式中。 - Martijn Pieters
你忘记调用 enumerate() 函数了,现在你没有一个 d 变量可以测试。 - Martijn Pieters
@MartijnPieters 是的,第二个枚举中d的丢失是我问题的关键。我会尝试你和@Jean-FrancoisFabre的建议,谢谢。 - slackline
在这种情况下,我强烈不同意。 - Sayse
@slackline:虽然列表推导式确实是一个更好的选项,用于通过简单地追加来构建列表的循环,但是你的循环做了比严格必要的工作还要多。 - Martijn Pieters
显示剩余2条评论
4个回答

12

你可以将其重写为以下形式:

new_list = [y for x in nested_list for d, y in enumerate(x) if d == 1]

循环以“自然”顺序进行,条件在最后。仅在d==1时包括y

一个可能的结果(因为字典没有顺序):

[{'c': 3, 'd': 4}, {'c': 7, 'd': 8}]

请注意,在您的情况下,更简单和更高效(O(n) vs O(n**2))的写法是:

new_list = [x[1] for x in nested_list]

唯一的区别是,如果x太短,后面的代码就会崩溃,因此可能需要测试长度:

区别仅在于,如果x过短,则后续代码将出错,建议测试字符串长度:

new_list = [x[1] for x in nested_list if len(x)>1]

谢谢,这真的很有用,特别是使用更短的x[1]方式来完成它,因为在我的实际用例中,嵌套列表的长度总是相同的。 - slackline

5
当我从嵌套循环转换到列表推导式时,我失去了从enumerate()获得的计数器。
那么你为什么要放弃它呢?列表推导式仍然可以使用所有与for循环相同的迭代器。
我在内部循环中有一个if语句,我不知道如何应用它。
只需将其放在同一位置即可。列表推导式对于for循环和if过滤器都遵循相同的嵌套顺序;您的循环可以通过删除冒号,并将.append(...)调用中的部分移到前面直接映射。
new_list = [y   # from new_list.append(y)
    for c, x in enumerate(nested_list)   # removed the :
        for d, y in enumerate(x)         # removed the :
            if d == 1]                   # removed the :

然而,您可以删除第一个enumerate(),因为您不使用c。您还可以删除第二个循环和enumerate(),因为您可以使用索引而不是循环:

new_list = [x[1] for x in nested_list]

在这里,您不需要循环遍历x中的所有值,那不是一个获取该值的高效方法。

如果您的问题是x列表可能较短并且没有第1个索引元素,请首先根据长度过滤这些嵌套列表:

new_list = [x[1] for x in nested_list if len(x) > 1]

谢谢,我只使用Python几个月,仍在学习中,没有意识到你可以保留if语句。非常清晰的解释,谢谢。 - slackline

1
你想要获取列表中每个数组的第二个元素,你可以这样做:
new_list = [nested_list[i][1] for i in range(len(nested_list))]

更好的做法
new_list  = [x[1] for x in nested_list]

0
print ([ y for c, x in enumerate(nested_list) for d, y in enumerate(x) if d == 1])

2
虽然这可能回答了作者的问题,但它缺少一些解释性的词语和文档链接。裸代码片段没有周围的一些短语是不太有帮助的。您也可以在如何撰写好的答案中找到很多帮助。请编辑您的答案。 - hellow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接