替换字符串中的子字符串

时间:2012-02-11 14:16:48

标签: python regex optimization replace

我的函数以字符串hex表示法(十六进制CSS颜色)查找并替换为短符号。
例如:#000000可以表示为#000

import re

def to_short_hex (string):
    match = re.findall(r'#[\w\d]{6}\b', string)

    for i in match:
        if not re.findall(r'#' + i[1] + '{6}', i):
            match.pop(match.index(i))

    for i in match:
        string = string.replace(i, i[:-3])

    return string;

to_short_hex('text #FFFFFF text #000000 #08088')

Out:

text #FFF text #000 #08088

有没有办法使用list comprehension等来优化我的代码。?

3 个答案:

答案 0 :(得分:3)

这个怎么样?您可以加快将is6hexdigit嵌入to_short_hex,但我希望它更具可读性。

hexdigits = "0123456789abcdef"

def is6hexdigit(sub):
    l = sub.lower()
    return (l[0] in hexdigits) and (l.count(l[0]) == 6)

def to_short_hex(may_have_hexes):
    replaced = ((sub[3:] if is6hexdigit(sub[:6]) else sub)
                        for sub in may_have_hexes.split('#'))
    return '#'.join(replaced)

答案 1 :(得分:2)

这就是re.sub的用途!使用正则表达式查找内容然后再进行一系列搜索和替换操作来更改它并不是一个好主意。一方面,很容易意外地替换你不想要的东西,另一方面,它会做很多多余的工作。

另外,您可能希望将'#aaccee'缩短为'#ace'。这个例子也是这样做的:

def to_short_hex(s):
    def shorten_match(match):
        hex_string = match.group(0)
        if hex_string[1::2]==hex_string[2::2]:
            return '#'+hex_string[1::2]
        return hex_string
    return re.sub(r"#[\da-fA-F]{6}\b", shorten_match, s)

解释

re.sub可以使用函数来应用于每个匹配。它接收匹配对象并返回该字符串以替换该点。

切片表示法允许您应用步幅。 hex_string [1 :: 2]从字符串中获取每隔一个字符,从索引1开始并运行到字符串的结尾。 hex_string [2 :: 2]从字符串中获取每隔一个字符,从索引2开始并运行到结尾。所以对于字符串“#aaccee”,我们得到匹配的“ace”和“ace”。对于字符串“#123456”,我们得到“135”和“246”,它们不匹配。

答案 2 :(得分:1)

在迭代上使用列表上的pop总是一个坏主意。因此,这不是优化,而是错误的纠正。另外,我修改了re以防止识别'#34j342'之类的字符串被接受:

>>> def to_short_hex(s):
...     matches = re.findall(r'#[\dabcdefABCDEF]{6}\b', s)
...     filtered = [m for m in matches if re.findall(r'#' + m[1] + '{6}', m)]
...     for m in filtered:
...         s = s.replace(m, m[:-3])
...     return s
... 
>>> to_short_hex('text #FFFFFF text #000000 #08088')
'text #FFF text #000 #08088'

此外,我认为re.search在第二个re中已经足够了。{/ p>