[python] 문자열에서 여러 문자를 바꾸는 가장 좋은 방법은 무엇입니까?

다음과 같이 일부 문자를 바꿔야합니다. &\&, #\#, …

나는 다음과 같이 코딩했지만 더 좋은 방법이 있어야한다고 생각합니다. 힌트가 있습니까?

strs = strs.replace('&', '\&')
strs = strs.replace('#', '\#')
...



답변

두 문자 교체

나는 현재 답변의 모든 방법을 하나 더 추가했습니다.

abc&def#ghi&-> \ & 및 #-> \ # 의 입력 문자열을 사용 하여 대체하는 가장 빠른 방법은 다음과 같이 대체를 연결하는 것 text.replace('&', '\&').replace('#', '\#')입니다.

각 기능의 타이밍 :

  • a) 1000000 루프, 루프 당 3 : 1.47 μs 최고
  • b) 1000000 루프, 루프 당 3 : 1 최고 1.51 μs
  • c) 100000 루프, 루프 당 3 : 12.3 μs
  • d) 100000 루프, 루프 당 3:12 μs 중 최고
  • e) 100000 루프, 루프 당 3 : 3.27 μs 중 최고
  • f) 1000000 루프, 루프 당 3 : 0.817 μs
  • g) 100000 루프, 루프 당 3 : 3.64 μs 중 최고
  • h) 1000000 루프, 루프 당 3 : 0.927 μs
  • i) 1000000 루프, 루프 당 3 : 최고 0.814 μs

기능은 다음과 같습니다.

def a(text):
    chars = "&#"
    for c in chars:
        text = text.replace(c, "\\" + c)


def b(text):
    for ch in ['&','#']:
        if ch in text:
            text = text.replace(ch,"\\"+ch)


import re
def c(text):
    rx = re.compile('([&#])')
    text = rx.sub(r'\\\1', text)


RX = re.compile('([&#])')
def d(text):
    text = RX.sub(r'\\\1', text)


def mk_esc(esc_chars):
    return lambda s: ''.join(['\\' + c if c in esc_chars else c for c in s])
esc = mk_esc('&#')
def e(text):
    esc(text)


def f(text):
    text = text.replace('&', '\&').replace('#', '\#')


def g(text):
    replacements = {"&": "\&", "#": "\#"}
    text = "".join([replacements.get(c, c) for c in text])


def h(text):
    text = text.replace('&', r'\&')
    text = text.replace('#', r'\#')


def i(text):
    text = text.replace('&', r'\&').replace('#', r'\#')

이 같은 시간 :

python -mtimeit -s"import time_functions" "time_functions.a('abc&def#ghi')"
python -mtimeit -s"import time_functions" "time_functions.b('abc&def#ghi')"
python -mtimeit -s"import time_functions" "time_functions.c('abc&def#ghi')"
python -mtimeit -s"import time_functions" "time_functions.d('abc&def#ghi')"
python -mtimeit -s"import time_functions" "time_functions.e('abc&def#ghi')"
python -mtimeit -s"import time_functions" "time_functions.f('abc&def#ghi')"
python -mtimeit -s"import time_functions" "time_functions.g('abc&def#ghi')"
python -mtimeit -s"import time_functions" "time_functions.h('abc&def#ghi')"
python -mtimeit -s"import time_functions" "time_functions.i('abc&def#ghi')"

17 자 교체

다음은 동일하지만 이스케이프 할 문자가 더 많은 유사한 코드입니다 (\`* _ {}> # +-.! $) :

def a(text):
    chars = "\\`*_{}[]()>#+-.!$"
    for c in chars:
        text = text.replace(c, "\\" + c)


def b(text):
    for ch in ['\\','`','*','_','{','}','[',']','(',')','>','#','+','-','.','!','$','\'']:
        if ch in text:
            text = text.replace(ch,"\\"+ch)


import re
def c(text):
    rx = re.compile('([&#])')
    text = rx.sub(r'\\\1', text)


RX = re.compile('([\\`*_{}[]()>#+-.!$])')
def d(text):
    text = RX.sub(r'\\\1', text)


def mk_esc(esc_chars):
    return lambda s: ''.join(['\\' + c if c in esc_chars else c for c in s])
esc = mk_esc('\\`*_{}[]()>#+-.!$')
def e(text):
    esc(text)


def f(text):
    text = text.replace('\\', '\\\\').replace('`', '\`').replace('*', '\*').replace('_', '\_').replace('{', '\{').replace('}', '\}').replace('[', '\[').replace(']', '\]').replace('(', '\(').replace(')', '\)').replace('>', '\>').replace('#', '\#').replace('+', '\+').replace('-', '\-').replace('.', '\.').replace('!', '\!').replace('$', '\$')


def g(text):
    replacements = {
        "\\": "\\\\",
        "`": "\`",
        "*": "\*",
        "_": "\_",
        "{": "\{",
        "}": "\}",
        "[": "\[",
        "]": "\]",
        "(": "\(",
        ")": "\)",
        ">": "\>",
        "#": "\#",
        "+": "\+",
        "-": "\-",
        ".": "\.",
        "!": "\!",
        "$": "\$",
    }
    text = "".join([replacements.get(c, c) for c in text])


def h(text):
    text = text.replace('\\', r'\\')
    text = text.replace('`', r'\`')
    text = text.replace('*', r'\*')
    text = text.replace('_', r'\_')
    text = text.replace('{', r'\{')
    text = text.replace('}', r'\}')
    text = text.replace('[', r'\[')
    text = text.replace(']', r'\]')
    text = text.replace('(', r'\(')
    text = text.replace(')', r'\)')
    text = text.replace('>', r'\>')
    text = text.replace('#', r'\#')
    text = text.replace('+', r'\+')
    text = text.replace('-', r'\-')
    text = text.replace('.', r'\.')
    text = text.replace('!', r'\!')
    text = text.replace('$', r'\$')


def i(text):
    text = text.replace('\\', r'\\').replace('`', r'\`').replace('*', r'\*').replace('_', r'\_').replace('{', r'\{').replace('}', r'\}').replace('[', r'\[').replace(']', r'\]').replace('(', r'\(').replace(')', r'\)').replace('>', r'\>').replace('#', r'\#').replace('+', r'\+').replace('-', r'\-').replace('.', r'\.').replace('!', r'\!').replace('$', r'\$')

동일한 입력 문자열에 대한 결과는 다음과 같습니다 abc&def#ghi.

  • a) 100000 루프, 루프 당 3 : 6.72 μs 최고
  • b) 100000 루프, 루프 당 3 : 3.64 μs 중 최고
  • c) 100000 루프, 루프 당 3 : 9.9 μs 중 최고
  • d) 100000 루프, 루프 당 3 : 3.92 μs 최고
  • e) 100000 루프, 루프 당 3 : 3.96 μs 최고
  • f) 100000 루프, 루프 당 3 : 3.29 μs 최고
  • g) 100000 루프, 루프 당 3 : 3.68 μs 중 최고
  • h) 100000 루프, 루프 당 3 : 3.73 μs 중 최고
  • i) 100000 루프, 루프 당 3 : 3.24 μs 최고

그리고 더 긴 입력 문자열 ( ## *Something* and [another] thing in a longer sentence with {more} things to replace$)

  • a) 100000 루프, 루프 당 3 : 59.59 μs
  • b) 100000 루프, 루프 당 3 : 6.54 μs
  • c) 100000 루프, 루프 당 최고 3 : 16.9 μs
  • d) 100000 루프, 루프 당 3 : 7.29 μs 최고
  • e) 100000 루프, 루프 당 3 : 12.2 μs 중 최고
  • f) 100000 루프, 루프 당 3 : 5.38 μs 최고
  • g) 10000 루프, 루프 당 3 : 3 최고 21.7 μs
  • h) 100000 루프, 루프 당 3 : 3 최고 5.7 μs
  • i) 100000 루프, 루프 당 3 : 5.13 μs 최고

몇 가지 변형 추가 :

def ab(text):
    for ch in ['\\','`','*','_','{','}','[',']','(',')','>','#','+','-','.','!','$','\'']:
        text = text.replace(ch,"\\"+ch)


def ba(text):
    chars = "\\`*_{}[]()>#+-.!$"
    for c in chars:
        if c in text:
            text = text.replace(c, "\\" + c)

더 짧은 입력으로 :

  • ab) 100000 루프, 루프 당 3 : 7.05 μs 중 최고
  • ba) 100000 루프, 루프 당 3 : 3μs 최고

더 긴 입력으로 :

  • ab) 100000 루프, 루프 당 최대 3 : 7.71 μs
  • ba) 100000 루프, 루프 당 3 : 6 : 08 μs 중 최고

ba가독성과 속도 를 위해 사용하겠습니다 .

추가

주석에서 haccks에 의해 프롬프트되며 , 확인 ab과 확인의 차이점은 하나 입니다. 두 가지 변형에 대해 테스트 해 보겠습니다.baif c in text:

def ab_with_check(text):
    for ch in ['\\','`','*','_','{','}','[',']','(',')','>','#','+','-','.','!','$','\'']:
        if ch in text:
            text = text.replace(ch,"\\"+ch)

def ba_without_check(text):
    chars = "\\`*_{}[]()>#+-.!$"
    for c in chars:
        text = text.replace(c, "\\" + c)

Python 2.7.14 및 3.6.3 및 이전 세트와 다른 시스템에서 루프 당 μs 시간은 직접 비교할 수 없습니다.

╭────────────╥──────┬───────────────┬──────┬──────────────────╮
 Py, input    ab   ab_with_check   ba   ba_without_check 
╞════════════╬══════╪═══════════════╪══════╪══════════════════╡
 Py2, short  8.81     4.22        3.45     8.01          
 Py3, short  5.54     1.34        1.46     5.34          
├────────────╫──────┼───────────────┼──────┼──────────────────┤
 Py2, long   9.3      7.15        6.85     8.55          
 Py3, long   7.43     4.38        4.41     7.02          
└────────────╨──────┴───────────────┴──────┴──────────────────┘

우리는 결론을 내릴 수 있습니다.

  • 수표가있는 사람은 수표가없는 사람보다 최대 4 배 빠릅니다.

  • ab_with_check파이썬 3에서는 약간 우위에 있지만, ba체크하면 파이썬 2에서는 우위에 있습니다.

  • 그러나 여기서 가장 큰 교훈은 Python 3이 Python 2보다 최대 3 배 빠릅니다 . 가장 느린 Python 3과 Python 2에서 가장 큰 차이는 없습니다!


답변

>>> string="abc&def#ghi"
>>> for ch in ['&','#']:
...   if ch in string:
...      string=string.replace(ch,"\\"+ch)
...
>>> print string
abc\&def\#ghi


답변

replace이와 같은 기능을 간단히 연결

strs = "abc&def#ghi"
print strs.replace('&', '\&').replace('#', '\#')
# abc\&def\#ghi

교체품이 더 많아 질 경우, 일반적인 방법으로이 작업을 수행 할 수 있습니다

strs, replacements = "abc&def#ghi", {"&": "\&", "#": "\#"}
print "".join([replacements.get(c, c) for c in strs])
# abc\&def\#ghi


답변

다음은 str.translateand를 사용하는 python3 방법입니다 str.maketrans.

s = "abc&def#ghi"
print(s.translate(str.maketrans({'&': '\&', '#': '\#'})))

인쇄 된 문자열은 abc\&def\#ghi입니다.


답변

항상 백 슬래시를 추가 하시겠습니까? 그렇다면 시도하십시오

import re
rx = re.compile('([&#])')
#                  ^^ fill in the characters here.
strs = rx.sub('\\\\\\1', strs)

가장 효율적인 방법은 아니지만 가장 쉬운 방법이라고 생각합니다.


답변

파티에 늦었지만 답변을 찾을 때 까지이 문제로 많은 시간을 잃었습니다.

짧고 달콤한, translate우월합니다replace . 시간 최적화에 따른 기능에 더 관심이있는 경우을 사용하지 마십시오 replace.

또한 사용하는 translate문자 집합을 대체하는 데 사용되는 문자 집합 중복 교체 할 경우 당신이 모르는 경우.

지목 사항:

를 사용 replace하면 코드 조각이 순진하게 "1234".replace("1", "2").replace("2", "3").replace("3", "4")반환 "2344"되지만 실제로 반환됩니다 "4444".

번역은 원래 OP가 원하는 것을 수행하는 것으로 보입니다.


답변

일반적인 이스케이프 함수 작성을 고려할 수 있습니다.

def mk_esc(esc_chars):
    return lambda s: ''.join(['\\' + c if c in esc_chars else c for c in s])

>>> esc = mk_esc('&#')
>>> print esc('Learn & be #1')
Learn \& be \#1

이 방법으로 이스케이프해야하는 문자 목록을 사용하여 기능을 구성 할 수 있습니다.