Python-从字符串创建集合

Python-从字符串创建集合,python,set,Python,Set,我有格式为1-36:10-117-9的字符串,我想根据它们创建如下的数字集{1,2,3,6,10,11,7,8,9} 对于从数字范围创建集合,我有以下代码: def create_set(src): lset = [] if len(src) > 0: pos = src.find('-') if pos != -1: first = int(src[:pos]) last = int(src

我有格式为1-36:10-117-9的字符串,我想根据它们创建如下的数字集{1,2,3,6,10,11,7,8,9}

对于从数字范围创建集合,我有以下代码:

def create_set(src):
    lset = []
    if len(src) > 0:
        pos = src.find('-')
        if pos != -1:
            first = int(src[:pos])
            last  = int(src[pos+1:])
        else:
            return [int(src)]  # Only one number
        for j in range (first, last+1): 
            lset.append(j)
        return set(lset)
但是,当“:”出现在字符串中时,我不知道如何正确处理它。有人能帮我吗

提前谢谢


编辑:顺便问一下,有没有一种更简洁的方法来解析这样的字符串,或者使用正则表达式?

类似的方法可能适合您:

s = '1-3 6:10-11 7-9'
s = s.replace(':', ' ')
lset = set()
fs = s.split()
for f in fs:
    r = f.split('-')
    if len(r)==1:
        # add a single number
        lset.add(int(r[0]))
    else:
        # add a range of numbers (inclusive of the endpoints)
        lset |= set(range(int(r[0]), int(r[1])+1))
print(lset)

这样的东西可能适合你:

s = '1-3 6:10-11 7-9'
s = s.replace(':', ' ')
lset = set()
fs = s.split()
for f in fs:
    r = f.split('-')
    if len(r)==1:
        # add a single number
        lset.add(int(r[0]))
    else:
        # add a range of numbers (inclusive of the endpoints)
        lset |= set(range(int(r[0]), int(r[1])+1))
print(lset)
编辑:顺便问一下,有没有更简洁的方法来解析这样的字符串, 也许使用正则表达式

也许是一种更干净、更高效的方法:

import re
import itertools

allGroups = re.findall(r"(\d+)(?:-(\d+)|:)", s)
expanded = [range(int(x), (int(x) if y == '' else int(y)) + 1) for x, y in allGroups]
print {x for x in itertools.chain.from_iterable(expanded)}
说明:

匹配所有字符串,如“a-b”或“a:”,并分别返回a、b和a对的列表:

allGroups = re.findall(r"(\d+)(?:-(\d+)|:)", s)
这将产生:

[('1', '3'), ('6', ''), ('10', '11'), ('7', '9')]
[[1, 2, 3], [6], [10, 11], [7, 8, 9]]
set([1, 2, 3, 6, 7, 8, 9, 10, 11])
使用列表理解,将所有x,y对展开为x,y+1范围内的完整数字列表,注意将x的大小写为x,x+1:

expanded = [range(int(x), (int(x) if y == '' else int(y)) + 1) for x, y in allGroups]
这将产生:

[('1', '3'), ('6', ''), ('10', '11'), ('7', '9')]
[[1, 2, 3], [6], [10, 11], [7, 8, 9]]
set([1, 2, 3, 6, 7, 8, 9, 10, 11])
使用itertools.chain.from_iterable将列表转换为单个iterable,该iterable通过集合理解迭代为最终集合:

print {x for x in itertools.chain.from_iterable(expanded)}
这将产生:

[('1', '3'), ('6', ''), ('10', '11'), ('7', '9')]
[[1, 2, 3], [6], [10, 11], [7, 8, 9]]
set([1, 2, 3, 6, 7, 8, 9, 10, 11])
编辑:顺便问一下,有没有更简洁的方法来解析这样的字符串, 也许使用正则表达式

也许是一种更干净、更高效的方法:

import re
import itertools

allGroups = re.findall(r"(\d+)(?:-(\d+)|:)", s)
expanded = [range(int(x), (int(x) if y == '' else int(y)) + 1) for x, y in allGroups]
print {x for x in itertools.chain.from_iterable(expanded)}
说明:

匹配所有字符串,如“a-b”或“a:”,并分别返回a、b和a对的列表:

allGroups = re.findall(r"(\d+)(?:-(\d+)|:)", s)
这将产生:

[('1', '3'), ('6', ''), ('10', '11'), ('7', '9')]
[[1, 2, 3], [6], [10, 11], [7, 8, 9]]
set([1, 2, 3, 6, 7, 8, 9, 10, 11])
使用列表理解,将所有x,y对展开为x,y+1范围内的完整数字列表,注意将x的大小写为x,x+1:

expanded = [range(int(x), (int(x) if y == '' else int(y)) + 1) for x, y in allGroups]
这将产生:

[('1', '3'), ('6', ''), ('10', '11'), ('7', '9')]
[[1, 2, 3], [6], [10, 11], [7, 8, 9]]
set([1, 2, 3, 6, 7, 8, 9, 10, 11])
使用itertools.chain.from_iterable将列表转换为单个iterable,该iterable通过集合理解迭代为最终集合:

print {x for x in itertools.chain.from_iterable(expanded)}
这将产生:

[('1', '3'), ('6', ''), ('10', '11'), ('7', '9')]
[[1, 2, 3], [6], [10, 11], [7, 8, 9]]
set([1, 2, 3, 6, 7, 8, 9, 10, 11])

我很想用正则表达式解析它-我不是专家,但我会这样做-因为“语法”似乎是正则的。@xnx我的想法正是为什么6有一个冒号?冒号表示它前面的数字应该作为集合中的单个元素添加。我尝试了xnx建议的解决方案,但它不起作用,因为原样代码无法将“1-2-3”这样的字符串识别为有效范围。我的意思是,为什么不能只使用范围或单个数字?然后在空格上拆分,并适当地处理范围,否则只需添加一个数字。我很想用正则表达式解析它-我不是专家,但我会这样做-因为“语法”似乎是正则的。@xnx我的想法正是为什么6有一个冒号?冒号表示它之前的数字应该作为集合中的单个元素添加。我尝试了xnx建议的解决方案,但它不起作用,因为原样代码无法将“1-2-3”这样的字符串识别为有效范围。我的意思是,为什么不能只使用范围或单个数字?然后在空格上拆分,并适当地处理范围,否则只需添加一个数字。这个答案很好,但下面的se表示一个替代的,可能更简单的选项。这个答案很好,但下面的se表示一个替代的,可能更简单的选项。谢谢,富士苹果,这个解决方案还具有返回排序的数字列表的优势。谢谢,富士苹果,此解决方案还具有返回已排序的数字列表的优点。