带有for循环的列表推导式中的if else。

3

我已经为列表展开编写了自己的简单解决方案:

lists = [0, 10, [20, 30], 40, 50, [60, 70, 80], [90, 100, 110, 120]]
new = []
for item in lists:
    if str(item).isdigit() != True:
        for v in item:
            new.append(v)
    else:
        new.append(item)
print(new)

然而我想要在下面的代码中添加一个else/elif,从而使代码更短:

new = [v for item in lists if str(item).isdigit() != True for v in item]

我不知道该怎么做,总是遇到语法错误。

2个回答

7

尝试这个:

>>> [v for item in lists for v in (item if isinstance(item, list) else [item])]
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120]

这种方法略显低效,它将一个整数封装成一个列表,然后迭代它,但对于大多数情况来说这应该没有太大关系。请尽量不要使用字符串表示来检查数据类型,因为您可能会得到意想不到的结果(例如,在列表中使用浮点数而不是整数运行原始代码)。


为了完整起见,我要提到:collections.abc.Iterable - Aaron
1
@Aaron 说实话,这感觉太麻烦了,而且也不可靠。调用 iter 并捕获异常是正确的方法,但这会使示例变得复杂并且失去重点。 - Selcuk
根据你的解决方案,我想出了我的新方案哈哈..谢谢伙计 :) new = [v for item in lists for v in (item if str(item).isdigit() != True else [item])] - Rishad

1
首先是您原始代码的一些注释:

  1. Instead of

    if str(item).isdigit() != True:
    

    use more Pythonic

    if not str(item).isdigit():
    
  2. Instead of the same, speculative way to reach your goal, use more clear

    if type(item) is not list:
    
现在,关于列表推导式中的else。它只能出现在第一部分,在for子句后(在if过滤表达式中)不允许使用。
因此,您需要更改列表推导式中第二个for中的可迭代对象,使其始终为可迭代对象,例如对于item
  • [20, 30]是可以的(因为它是一个可迭代对象)
  • 10不行(因为它不是可迭代对象),所以让我们在它周围加上括号- [10]
因此,我们将根据type(item)item[item]之间切换:
 item     if type(item) is list     else     [item]

(这是一个条件表达式,而不是列表推导式,因此在这里使用else是可以的。)
因此完整的解决方案可能是:
new = [v for item in lists 
         for v in (item if type(item) is list else [item])]

你描述这个事实的准确度令人难以置信,谢谢你的帮助伙计! - Rishad

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