Python 使用理解函数拆分并展平字符串和无值的列表

Python 使用理解函数拆分并展平字符串和无值的列表,python,python-3.x,generator,list-comprehension,itertools,Python,Python 3.x,Generator,List Comprehension,Itertools,给定一个同时包含string和None值的列表,其中一些字符串嵌入了换行符,我希望将带有换行符的字符串拆分为多个字符串,并返回一个展开的列表 我已经编写了使用生成器函数来实现这一点的代码,但是代码相当庞大,我想知道是否可以使用列表理解或模块中的函数来更简洁地实现这一点itertools.chain似乎无法拒绝迭代任何不可iter的元素 def expand_newlines(lines): r"""Split strings with newlines into multiple str

给定一个同时包含string和None值的列表,其中一些字符串嵌入了换行符,我希望将带有换行符的字符串拆分为多个字符串,并返回一个展开的列表

我已经编写了使用生成器函数来实现这一点的代码,但是代码相当庞大,我想知道是否可以使用列表理解或模块中的函数来更简洁地实现这一点
itertools.chain
似乎无法拒绝迭代任何不可iter的元素

def expand_newlines(lines):
    r"""Split strings with newlines into multiple strings.

    >>> l = ["1\n2\n3", None, "4\n5\n6"]
    >>> list(expand_newlines(l))
    ['1', '2', '3', None, '4', '5', '6']
    """
    for line in lines:
        if line is None:
            yield line
        else:
            for l in line.split('\n'):
                yield l

您可以使用来自的
收益率

def expand(lines):
    for line in lines:
        if isinstance(line,str):
            yield from line.split('\n')
        elif line is None:
            yield line


这里只有一行,但我认为@Ch3steR的解决方案更具可读性

from itertools import chain

list(chain.from_iterable(i.splitlines() if i is not None and '\n' in i else [i] 
                         for i in lines))

如果您可以在原地修改列表,则可以执行以下操作:

lst = ["1\n2\n3", None, "4\n5\n6"]
for i in range(len(lst))[::-1]:
    if isinstance(lst[i], str):
        lst[i:i+1] = lst[i].split("\n")
print(lst)  # ['1', '2', '3', None, '4', '5', '6']

此解决方案利用了这样一个事实,即您不仅可以获取python的列表切片,还可以将其分配给它们。它从右向左移动,否则我将需要计算额外的项目,这将使它变得更加困难。

如果您执行以下操作,则可以使用itertools.chain

import itertools

def expand_newlines(lines):

    return itertools.chain.from_iterable(x.split("\n") if x else [None]
                                         for x in lines)

与@bluetooth的答案类似,但通过颠倒逻辑更简洁:

import itertools
chainfi = itertools.chain.from_iterable

def expand_newlines(lines):
    r"""Split strings with newlines into multiple strings.

    >>> l = ["1\n2\n3", None, "4\n5\n6"]
    >>> list(expand_newlines(l))
    ['1', '2', '3', None, '4', '5', '6']
    """
    return chainfi([None] if l is None else l.split('\n') for l in lines)
None
是特殊情况,因此我们应该检查它

这足够简洁,我甚至不需要为它编写函数——我只是将它保存在函数中,以通过doctest确认它的工作情况。

用于展平嵌套列表:

给定的

import more_itertools as mit


lst = ["1\n2\n3", None, "7\n8\n9"]
演示

list(mit.collapse([x.split("\n") if x else x for x in lst ]))

# ['1', '2', '3', None, '7', '8', '9']

是第三方软件包。通过
>安装pip Install more\u itertools

如果python支持*作为列表的操作符,那就太好了:(*x.split(“\n”),如果x在行中没有,那么x就没有了),但是我认为它不会。啊哈!如果我用另一种方式,它会更紧凑,请看我的答案。
中获得收益很有用,我不知道这种语法(仍然习惯于python 3哈哈)。这基本上是我问题中的代码,不过,刚刚清理了一点。
list(mit.collapse([x.split("\n") if x else x for x in lst ]))

# ['1', '2', '3', None, '7', '8', '9']