Заменить подстроку в строке - PullRequest
1 голос
/ 11 февраля 2012

Моя функция находит в строке 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 ]

3 голосов
/ 11 февраля 2012

Как насчет этого? Вы можете ускорить встраивание 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)
2 голосов
/ 11 февраля 2012

Вот для чего 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", которые не совпадают.

1 голос
/ 11 февраля 2012

Использование 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...