2010-06-09 16 views
6

Potrzebuję zamienić ciąg znaków w sposób uwzględniający wielkość liter. Na przykład:Rozróżnianie wielkości liter w pytaniu w Pythonie

 
abc -> def 
Abc -> Def 
aBc -> dEf 
abC -> deF 

Co mogę zrobić z Pythonem?

+0

@Mark: wiki wykorzystuje górna/dolna znaków dla nazwy wiki. Muszę zastąpić niektóre nazwy wiki. – prosseek

+0

Jaki byłby zamiennik "WSg"? – joaquin

+0

Jest możliwe, że odpowiedź na zadane pytanie nie pomoże w rozwiązaniu problemu, który próbujesz rozwiązać. Co jeśli przed i po mają różne długości? –

Odpowiedz

7
from string import maketrans 

"Abc".translate(maketrans("abcABC", "defDEF")) 
+2

Zakłada się, że ten sam znak nie pojawia się dwukrotnie w ciągu wejściowym. –

+3

To nie zadziała dla zamiany "foo" na "bar", ponieważ znak "o" musi być odwzorowany na "a" lub "r" w zależności od kontekstu. –

0

Moduł re jest prawdopodobnie tym, czego szukasz. W szczególności funkcja re.sub może być wykorzystana do prostego wyszukiwania/zamiany ciągów znaków.

+0

're.sub' nie zachowuje oryginalnej wielkości liter w łańcuchu. Jeśli dobrze rozumiem, oryginalny plakat chce zachować wielkość liter. –

+0

@Tam Ah, po ponownym przeczytaniu pytania, chyba źle zrozumiałem, o co prosił.Jeśli szuka efektywnego, niewrażliwego na wielkość znaków zastępującego łańcuch, po którym następuje "make case pasuje do poprzedniej wersji", to tak, 're.sub' nie będzie właściwym rozwiązaniem ... chyba że funkcja niestandardowa zostanie przekazana jako argument zastępczy. Nawet wtedy, prawdopodobnie nie. – Rakis

0

Nie jest to najbardziej efektywny sposób, i to jest bardzo surowy, ale chyba coś takiego może działać:

def case_insensitive_replace(string, old, new): 
    upper_indices = [idx for idx, char in enumerate(string) if char.isupper()] 
    replaced = list(string.lower().replace(old.lower(), new.lower())) 
    for idx in upper_indices: 
     replaced[idx] = replaced[idx].upper() 
    return "".join(replaced) 
5

Oto metoda za pomocą wyrażeń regularnych. Kluczową kwestią jest to, że po znalezieniu dopasowania najpierw modyfikuje zastępczy ciąg, dopasowany do obudowy dopasowanego ciągu. Działa to, ponieważ re.sub może przyjąć funkcję zastępczą zamiast tylko ciąg.

import re 

def case_sensitive_replace(s, before, after): 
    regex = re.compile(re.escape(before), re.I) 
    return regex.sub(lambda x: ''.join(d.upper() if c.isupper() else d.lower() 
             for c,d in zip(x.group(), after)), s) 

test = ''' 
abc -> def 
Abc -> Def 
aBc -> dEf 
abC -> deF 
''' 

result = case_sensitive_replace(a, 'abc', 'def') 
print(result) 

Wynik:

 
def -> def 
Def -> Def 
dEf -> dEf 
deF -> deF 
0

Rozumiem, że chcesz zmienić drugi przypadek ciąg według pierwszego łańcucha. Mam rację? Moje rozwiązanie jest następujące. Łańcuch s2 zmienia wielkość liter zgodnie z odpowiadającym ciągiem s1. Wynik jest zapisywany w s3. Jednym z założeń jest to, że dwa łańcuchy mają tę samą długość.

s1 = "AaBb" 
s2 = "cdef" 
s3 = "" 
index = 0 
length = len(s1) 

while(True): 
    if s1[index].isupper(): 
     temp = s2[index].upper() 
    else: 
     temp = s2[index].lower() 
    s3 = s3 + temp 
    index +=1 
    if index == length: 
     break 
print s3 
1

Długo czaić się, myślałem, że zamieszczę tutaj sugestię, ponieważ niektóre z nich wydają się dość zawiłe.

print map(lambda a, b: b.lower() if a.islower() else b.upper(), "aBc", "def") 

Czyni zakładać oba łańcuchy są tej samej długości, jednak można łatwo zastąpić lambda z właściwą funkcję i sprawdzić Żaden pierwszego wejścia.

0

To będzie działać, chociaż prawdopodobnie chcesz dodać kilka czeków, że długości strun są takie same:

string1 = "AbcDEFghiJKLmnO" 
string2 = "some other text" 

string2 = "".join((string2[i].upper() if string1[i].isupper() else string2[i].lower() 
        for i in range(len(string1)))) 
2

Rozwijając na odpowiedź Mark Byers', Oto rozwiązanie, które działa dla tekstu zastępczego o dowolnej długości.
Sztuką jest wysłanie funkcji do re.sub().

import re 
def case_sensitive_replace(string, old, new): 
    """ replace occurrences of old with new, within string 
     replacements will match the case of the text it replaces 
    """ 
    def repl(match): 
     current = match.group() 
     result = '' 
     all_upper=True 
     for i,c in enumerate(current): 
      if i >= len(new): 
       break 
      if c.isupper(): 
       result += new[i].upper() 
      else: 
       result += new[i].lower() 
       all_upper=False 
     #append any remaining characters from new 
     if all_upper: 
      result += new[i+1:].upper() 
     else: 
      result += new[i+1:].lower() 
     return result 

    regex = re.compile(re.escape(old), re.I) 
    return regex.sub(repl, string) 

print case_sensitive_replace("abc Abc aBc abC ABC",'abc','de') 
print case_sensitive_replace("abc Abc aBc abC ABC",'abc','def') 
print case_sensitive_replace("abc Abc aBc abC ABC",'abc','defg') 

Wynik:

de De dE de DE 
def Def dEf deF DEF 
defg Defg dEfg deFg DEFG 
Powiązane problemy