22

'Agh#$%#%2341- -!zdrkfd' のような文字列を想像してみてください。小文字のみが返されるように操作を実行したいだけです (例として)。この場合は 'ghzdrkfd になります。 '。

Pythonでこれをどのように行いますか? 明らかな方法は、「a」から「z」までの文字のリストを作成し、文字列内の文字を繰り返し処理して、リスト内の文字のみから文字ごとに新しい文字列を作成することです。これは原始的なようです。

正規表現が適切かどうか疑問に思っていました。不要な文字を置き換えるのは問題があるようで、ブラックリストよりもホワイトリストを好む傾向があります。機能が適切では.matchないようです。Python サイトの適切なページを調べましたが、適合すると思われる方法が見つかりませんでした。

正規表現が適切でなく、正しいアプローチがループである場合、文字列をリストに「分解」する単純な関数はありますか? それとも、別の for ループを打っているだけですか?

4

10 に答える 10

32

効率を求めるなら。翻訳機能を使用するのが最速です。

文字をすばやく置き換えたり、削除したりするために使用できます。

import string
delete_table  = string.maketrans(
    string.ascii_lowercase, ' ' * len(string.ascii_lowercase)
)
table = string.maketrans('', '')

"Agh#$%#%2341- -!zdrkfd".translate(table, delete_table)

Python 2.6 では、2 番目のテーブルはもう必要ありません。

import string
delete_table  = string.maketrans(
    string.ascii_lowercase, ' ' * len(string.ascii_lowercase)
)
"Agh#$%#%2341- -!zdrkfd".translate(None, delete_table)

これは、他の方法よりもはるかに高速な方法です。もちろん、delete_table をどこかに保存して使用する必要があります。ただし、毎回保存してビルドしなくても、これまでに提案された他の方法よりも高速になります。

私の主張を確認するために、結果は次のとおりです。

for i in xrange(10000):
    ''.join(c for c in s if c.islower())

real    0m0.189s
user    0m0.176s
sys 0m0.012s

正規表現ソリューションの実行中:

for i in xrange(10000):
    re.sub(r'[^a-z]', '', s)

real    0m0.172s
user    0m0.164s
sys 0m0.004s

【ご要望に応じて】正規表現をプリコンパイルする場合:

r = re.compile(r'[^a-z]')
for i in xrange(10000):
    r.sub('', s)

real    0m0.166s
user    0m0.144s
sys 0m0.008s

translate メソッドを同じ回数実行すると、次のようになります。

real    0m0.075s
user    0m0.064s
sys 0m0.012s
于 2009-05-15T20:35:58.343 に答える
18
s = 'Agh#$%#%2341- -!zdrkfd'  
print ''.join(c for c in s if c.islower())

文字列オブジェクトは反復可能です。文字列をリストに「分解」する必要はありません。リスト内包表記にはどんな条件でも入れることができ、それに応じて文字をフィルタリングします。

正規表現を使用してこれを実装することもできますが、これはループを隠すだけです。正規表現ライブラリは、文字列をフィルタリングするために文字列をループする必要があります。

于 2009-05-15T19:53:36.963 に答える
5

特に次のシナリオでは、正規表現を使用するのは簡単です。

>>> import re
>>> s = 'ASDjifjASFJ7364'
>>> re.sub(r'[^a-z]+', '', s)
'jifj'

これを何度も行う予定がある場合は、事前に正規表現をコンパイルすることをお勧めします。

>>> import re
>>> s = 'ASDjifjASFJ7364'
>>> r = re.compile(r'[^a-z]+')
>>> r.sub('', s)
'jifj'
于 2009-05-15T19:58:27.373 に答える
4
s = 'ASDjifjASFJ7364'
s_lowercase = ''.join(filter(lambda c: c.islower(), s))
print s_lowercase #print 'jifj'
于 2009-05-15T19:53:32.500 に答える
4
>>> s = 'Agh#$%#%2341- -!zdrkfd'
>>> ''.join(i for i in s if  i in 'qwertyuiopasdfghjklzxcvbnm')
'ghzdrkfd'
于 2009-05-15T19:57:34.987 に答える
1

文字列の操作に特に関心がある場合の解決策の 1 つを次に示します。

 s = 'Agh#$%#%2341- -!zdrkfd'
 lowercase_chars = [chr(i) for i in xrange(ord('a'), ord('z') + 1)]
 whitelist = set(lowercase_chars)
 filtered_list = [c for c in s if c in whitelist]

ホワイトリストは、実際には効率のためのセット (リストではありません) です。

文字列が必要な場合は、join() を使用します。

filtered_str = ''.join(filtered_list)

filter() は、より一般的なソリューションです。ドキュメントから ( http://docs.python.org/library/functions.html ):

filter(関数、反復可能)

関数が true を返す iterable の要素からリストを作成します。iterable は、シーケンス、反復をサポートするコンテナー、または反復子のいずれかです。iterable が文字列またはタプルの場合、結果もその型になります。それ以外の場合は常にリストです。function が None の場合、恒等関数が想定されます。つまり、false である iterable のすべての要素が削除されます。

これは、filter() を使用する 1 つの方法です。

filtered_list = filter(lambda c: c.islower(), s)
于 2009-05-15T20:59:53.403 に答える
0
import string
print "".join([c for c in "Agh#$%#%2341- -!zdrkfd" if c in string.lowercase])
于 2009-05-15T20:04:29.993 に答える
0
import string

print filter(string.lowercase.__contains__, "lowerUPPER")
print filter("123".__contains__, "a1b2c3")
于 2015-04-28T16:54:47.237 に答える
0

私は正規表現を使用します。小文字の一致 [az]。

于 2009-05-15T19:54:27.443 に答える