我在Python中有一個unicode字符串,基本上需要經過一個字符的逐個字符並根據規則列表替換某些字符串。一個這樣的規則是如果a
在n
之後a
改爲ö
。另外,如果一行中有兩個元音字符,它們將被一個元音字符和:
取代。所以,如果我有字符串"natarook"
,獲取"nötaro:k"
最簡單和最有效的方法是什麼?如果有問題的話,使用Python 2.6和CherryPy 3.1。如何在字符串中進行有條件的字符替換
編輯:連續兩個元音並不意味着同樣的元音(OO,AA,II)
我在Python中有一個unicode字符串,基本上需要經過一個字符的逐個字符並根據規則列表替換某些字符串。一個這樣的規則是如果a
在n
之後a
改爲ö
。另外,如果一行中有兩個元音字符,它們將被一個元音字符和:
取代。所以,如果我有字符串"natarook"
,獲取"nötaro:k"
最簡單和最有效的方法是什麼?如果有問題的話,使用Python 2.6和CherryPy 3.1。如何在字符串中進行有條件的字符替換
編輯:連續兩個元音並不意味着同樣的元音(OO,AA,II)
# -*- coding: utf-8 -*-
def subpairs(s, prefix, suffix):
def sub(i, sentinal=object()):
r = prefix.get(s[i:i+2], sentinal)
if r is not sentinal: return r
r = suffix.get(s[i-1:i+1], sentinal)
if r is not sentinal: return r
return s[i]
s = '\0'+s+'\0'
return ''.join(sub(i) for i in xrange(1,len(s)))
vowels = [(v+v, u':') for v in 'aeiou']
prefix = {}
suffix = {'na':u'ö'}
suffix.update(vowels)
print subpairs('natarook', prefix, suffix)
# prints: nötaro:k
prefix = {'na':u'ö'}
suffix = dict(vowels)
print subpairs('natarook', prefix, suffix)
# prints: öataro:k
這是一個原始的想法,但也許你想要將其解釋爲OP ;-) – RedGlyph 2009-12-04 20:10:35
這是一個好點! Dispatch是(previous + current)字符對的表格。子對使用\ 0對字符串進行成對迭代以表示字符串開始。每個配對都在配送表中查找替代使用。如果沒有發現,get返回當前字符「c」。算法是線性複雜度 - O(n)。 – 2009-12-04 20:22:35
另外,我怎樣才能在規則之前做到這一點?因此,對於'na':u'ö',將'n'改爲'ö'而不是'a' – roflwaffle 2009-12-07 15:15:02
鑑於你的規則,我說你真的想要一個簡單的狀態機。嗯,第二個想法,也許不是;你可以隨時回頭看看字符串。
我在Python中有一個unicode字符串,基本上需要逐個字符地逐個字符,並根據規則列表替換某些字符串。一個這樣的規則是,如果a在n之後,則a被改變爲ö。另外,如果一行中有兩個元音字符,它們將被一個元音字符和:替換。所以如果我有字符串,獲取「nötaro:k」最簡單和最有效的方法是什麼?如果有問題的話,使用Python 2.6和CherryPy 3.1。
vowel_set = frozenset(['a', 'e', 'i', 'o', 'u', 'ö'])
def fix_the_string(s):
lst = []
for i, ch in enumerate(s):
if ch == 'a' and lst and lst[-1] == 'n':
lst.append('ö')
else if ch in vowel_set and lst and lst[-1] in vowel_set:
lst[-1] = 'a' # "replaced by one vowel character", not sure what you want
lst.append(':')
else
lst.append(ch)
return "".join(lst)
print fix_the_string("natarook")
編輯:現在,我看到@Anon的答案。我認爲這是最簡單的方法。一旦你獲得了大量的規則,這實際上可能會更快,因爲它會傳遞一個字符串;但可能不會,因爲Python中的正則表達式是快速的C代碼。
但是越簡單越好。下面是正則表達式的方法實際的Python代碼:「我知道,我將使用正則表達式」
import re
pat_na = re.compile(r'na')
pat_double_vowel = re.compile(r'([aeiou])[aeiou]')
def fix_the_string(s):
s = re.sub(pat_na, r'nö', s)
s = re.sub(pat_double_vowel, r'\1:', s)
return s
print fix_the_string("natarook") # prints "nötaro:k"
不能'lst'只是一個字符串? – RedGlyph 2009-12-04 20:12:49
而不是我們可以使用一個字符串。但字符串在Python中是不可變的,我們不能只替換最後一個字符;我們必須做一些事情,比如's_new = s_new [: - 1] + new_ch'。真正的問題是性能真的很糟糕。附加到列表或替換元素是一種快速操作,但追加到字符串涉及將字符串複製到新字符串,然後添加新字符;這給了O(N ** 2)的表現,非常糟糕。最近的Python版本已經優化了這個特定的情況,至少在某些時候,但這是實現它的傳統方式。 – steveha 2009-12-04 20:21:22
@steveha:小心,你正在測試對最後輸出的字符('LST [-1]'),而不是對以前輸入的字符 - 這取決於還有什麼是在OP的全套規則,這可能是一個很好的想法或一個壞主意。 – 2009-12-04 20:42:31
但嚴重的是,正則表達式對於字符串操作確實很好。
你可以寫每一個規則,像這樣:
s/na/nö/g
s/([aeiou])$1/$1:/g
或者你也可以在運行時從其中列出了他們所有其他來源產生它們。
專注於容易和正確首先,然後考慮效率,如果分析表明其瓶頸。
簡單的方法是:
prev = None
for ch in string:
if ch == 'a':
if prev == 'n':
...
prev = ch
這可能是簡單的做用正則表達式的手工製作的列表,而不是progmatically gererating他們。我推薦以下代碼。
import re
# regsubs is a dictionary of regular expressions as keys,
# and the replacement regexps as values
regsubs = {'na':u'nö',
'([aeiou])\\1': '\\1:'}
def makesubs(s):
for pattern, repl in regsubs.iteritems():
s = re.sub(pattern, repl, s)
return s
print makesubs('natarook')
# prints: nötaro:k
您需要更清楚地瞭解您的「連續兩個元音字符」規則 - 一個假設它適用於「book」,但不適用於「bear」。 – 2009-12-04 20:32:41
這就像拔牙 - 如果兩個元音字符不需要相同,哪一個出現在替換中? – 2009-12-05 00:44:16
是的,我的意思是連續兩個雙元音(ii,aa,oo) – roflwaffle 2009-12-05 06:57:23