使用生成器表达式有什么问题?

时间:2019-07-07 22:26:51

标签: python generator

我有以下代码,在其中我尝试将范围的字符串表示形式转换为数字列表。例如,如果输入为'0-0,3-5,7-10',则预期输出为[0,3,4,5,7,8,9,10]。但是,我在以下位置出现错误:

for l,h in r.split('-') 

表示没有足够的值可解压。我的理由是,r的格式应为'x-y',因此,如果将其除以'-',则应该返回两个值。怎么了?

def parse_ranges(ranges):
    """Return a list of numbers corresponding to number ranges in a string"""
    g = (
        (l,h)
        for r in ranges.split(',')
        for l,h in r.split('-')
        )
    return (x
            for range_tuple in g
            for l,h in range_tuple
            for x in range(int(l), int(h)+1)
            )

parse_ranges('0-5,8-10,11-13')

4 个答案:

答案 0 :(得分:1)

您的循环太多了。由于您试图将两个数字保持在一起,因此不需要第二个嵌套循环。第二个是将结果展平:

>>> [x for r in s.split(',') for x in r.split('-')]
['0', '0', '3', '5', '7', '10']

使用一个使数字保持配对:

>>> [r.split('-') for r in s.split(',')]
[['0', '0'], ['3', '5'], ['7', '10']]

然后通过第二个理解,可以通过解压缩forl的位置来组合前两个h循环。

return (x
        for l,h in g
        for x in range(int(l), int(h)+1)
        )

答案 1 :(得分:1)

intspan module就是这样做的。

import intspan
s =  '0-0,3-5,7-10'

>>> list(intspan.intspan(s))
[0, 3, 4, 5, 7, 8, 9, 10]

答案 2 :(得分:0)

如果您的目标是将具有这种格式的字符串解析为一个整数列表,那么可能值得使用正则表达式对其进行解析

def parse_ranges(ranges):
    """Return a list of numbers corresponding to number ranges in a string"""
    return re.split(',|-', ranges)

parse_ranges('0-5,8-10,11-13')

输出:

['0', '5', '8', '10', '11', '13']

要以整数而不是字符串的形式获取它们,可以执行以下操作:

def parse_ranges(ranges):
    """Return a list of numbers corresponding to number ranges in a string"""
    return (int(x) for x in re.split(',|-', ranges))

list(parse_ranges('0-5,8-10,11-13'))

输出:

[0, 5, 8, 10, 11, 13]

答案 3 :(得分:0)

我一直无法弄清楚如何避免将每个范围字符串分割两次,但是由于效率低下,可以将其变成单个表达式:

def parse_ranges(ranges):
    return tuple(x for r in
                    (range(int(pair.split('-')[0]), int(pair.split('-')[1])+1)
                        for pair in
                            ranges.split(',')) for x in r)

print(parse_ranges('0-0,3-5,7-10'))  # -> (0, 3, 4, 5, 7, 8, 9, 10)