This告诉我们准备一个数字列表的方法,包括一系列连续数字或不连续数字。
例如,list(range(1,10)) + [20,30,40] + list(range(400,410))
将返回[1, 2, 3, 4, 5, 6, 7, 8, 9, 20, 30, 40, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409]
。
但是我可以通过输入像"1-10, 20, 30, 40, 400-410"
这样的字符串来简化它吗?
我可以使用for循环编写一个函数来查看数字。有没有一种更有效的方法来编写函数而不使用for-loop?
答案 0 :(得分:1)
您可以使用嵌套列表推导,检查当前部分是否包含-
并使用range
或相应地创建单一列表:
>>> s = "1-10, 20, 30, 40, 400-410"
>>> [n for part in s.split(", ") for n in (range(*map(int, part.split("-"))) if "-" in part else [int(part)])]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 20, 30, 40, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409]
为了便于阅读,可能会将其分开:
>>> to_list = lambda part: range(*map(int, part.split("-"))) if "-" in part else [int(part)]
>>> [n for part in s.split(", ") for n in to_list(part)]
注意:与第一个示例一样,这会将"1-10"
翻译为[1, 2, ..., 9]
,而不会10
。
正如评论中所述,这不适用于负数,但是尝试将-3
或-4--2
分成数字对。为此,您可以使用正则表达式...
>>> def to_list(part):
... m =re.findall(r"(-?\d+)-(-?\d+)", part)
... return range(*map(int, m[0])) if m else [int(part)]
...
>>> s = "-10--5, -4, -2-3"
>>> [n for part in s.split(", ") for n in to_list(part)]
[-10, -9, -8, -7, -6, -4, -2, -1, 0, 1, 2]
...或者只是对范围使用不同的分隔符,例如-10:-5
。
答案 1 :(得分:0)
我建议您改为编写一个允许创建更复杂的分段范围的函数。
def piecewise_range(*args):
for arg in args:
yield from range(*arg)
piecewise_range((1, 10), (20, 50, 10), (400, 410))
函数piecewise_range
然后输出一个生成器,因此它允许您拥有更复杂的范围模式并保持range
懒惰。
答案 2 :(得分:0)
根据输入字符串的来源,您可能会使用这样的内容,命名为您想要命名的内容:
import re
def gen_nums(input_string):
out = []
for item in re.split(r',\s*', input_string):
if '-' in item:
start, end = item.split('-')
out.extend(range(int(start), int(end)))
else:
out.append(int(item))
return out