Pythonを使用して、文字列から英数字以外のすべての文字を削除する最良の方法は何ですか?
この質問のPHPバリアントで提示される解決策は、おそらくいくつかの小さな調整で機能しますが、私にはあまり「Pythonic」ではないようです。
参考までに、ピリオドとコンマ(およびその他の句読点)だけでなく、引用符、角かっこなども削除する必要があります。
Pythonを使用して、文字列から英数字以外のすべての文字を削除する最良の方法は何ですか?
この質問のPHPバリアントで提示される解決策は、おそらくいくつかの小さな調整で機能しますが、私にはあまり「Pythonic」ではないようです。
参考までに、ピリオドとコンマ(およびその他の句読点)だけでなく、引用符、角かっこなども削除する必要があります。
回答:
好奇心からいくつかの機能の時間を計ったところです。これらのテストでは、文字列string.printable
(組み込みstring
モジュールの一部)から英数字以外の文字を削除しています。コンパイルの使用'[\W_]+'
とは、pattern.sub('', str)
最速であることが判明しました。
$ python -m timeit -s \
"import string" \
"''.join(ch for ch in string.printable if ch.isalnum())"
10000 loops, best of 3: 57.6 usec per loop
$ python -m timeit -s \
"import string" \
"filter(str.isalnum, string.printable)"
10000 loops, best of 3: 37.9 usec per loop
$ python -m timeit -s \
"import re, string" \
"re.sub('[\W_]', '', string.printable)"
10000 loops, best of 3: 27.5 usec per loop
$ python -m timeit -s \
"import re, string" \
"re.sub('[\W_]+', '', string.printable)"
100000 loops, best of 3: 15 usec per loop
$ python -m timeit -s \
"import re, string; pattern = re.compile('[\W_]+')" \
"pattern.sub('', string.printable)"
100000 loops, best of 3: 11.2 usec per loop
valid_characters = string.ascii_letters + string.digits
が続くjoin(ch for ch in string.printable if ch in valid_characters)
と、それはより速くより6マイクロ秒だったisalnum()
。。オプションそれでもかなり遅い正規表現よりもかかわらず
pattern.sub('', string.printable)
、REオブジェクトがあるときにre.subを呼び出すのはばかげています!-)。
re.compile('[\W_]+', re.UNICODE)
それをunicode安全にするために使用します。
救助のための正規表現:
import re
re.sub(r'\W+', '', your_string)
Pythonの定義により
'\W
==[^a-zA-Z0-9_]
、除外すべてnumbers
、letters
および_
\W
アンダースコアも保持します。
str.translate()メソッドを使用します。
これを頻繁に行うと想定します。
(1)一度、削除したいすべての文字を含む文字列を作成します。
delchars = ''.join(c for c in map(chr, range(256)) if not c.isalnum())
(2)文字列を削除したいときはいつでも:
scrunched = s.translate(None, delchars)
セットアップのコストは、おそらくre.compileに匹敵します。限界費用はずっと低いです:
C:\junk>\python26\python -mtimeit -s"import string;d=''.join(c for c in map(chr,range(256)) if not c.isalnum());s=string.printable" "s.translate(None,d)"
100000 loops, best of 3: 2.04 usec per loop
C:\junk>\python26\python -mtimeit -s"import re,string;s=string.printable;r=re.compile(r'[\W_]+')" "r.sub('',s)"
100000 loops, best of 3: 7.34 usec per loop
注:string.printableをベンチマークデータとして使用すると、パターン '[\ W _] +'が不当に有利になります。英数字以外のすべての文字が1つの束に含まれています...一般的なデータでは、複数の置換が必要です。
C:\junk>\python26\python -c "import string; s = string.printable; print len(s),repr(s)"
100 '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
re.subにもう少し作業を行わせると、次のようになります。
C:\junk>\python26\python -mtimeit -s"d=''.join(c for c in map(chr,range(256)) if not c.isalnum());s='foo-'*25" "s.translate(None,d)"
1000000 loops, best of 3: 1.97 usec per loop
C:\junk>\python26\python -mtimeit -s"import re;s='foo-'*25;r=re.compile(r'[\W_]+')" "r.sub('',s)"
10000 loops, best of 3: 26.4 usec per loop
string.punctuation
代わりに''.join(c for c in map(chr, range(256)) if not c.isalnum())
str
オブジェクトに対しては機能しますが、オブジェクトに対しては機能しないことに注意してくださいunicode
。
.join()
ですか?
>>> import re
>>> string = "Kl13@£$%[};'\""
>>> pattern = re.compile('\W')
>>> string = re.sub(pattern, '', string)
>>> print string
Kl13
どうですか:
def ExtractAlphanumeric(InputString):
from string import ascii_letters, digits
return "".join([ch for ch in InputString if ch in (ascii_letters + digits)])
これは、リスト内包表記を使用して、文字がInputString
結合さascii_letters
れたdigits
文字列に存在する場合に、文字のリストを生成することによって機能します。次に、リストを結合して文字列にします。
ここで他のいくつかの回答からのスピンオフとして、文字列のコンテンツを制限したい文字のセットを定義するための本当にシンプルで柔軟な方法を提供します。この場合、英数字とダッシュとアンダースコアを使用できます。PERMITTED_CHARS
ユースケースに合わせて、myに文字を追加または削除してください。
PERMITTED_CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-"
someString = "".join(c for c in someString if c in PERMITTED_CHARS)
string.digits + string.ascii_letters + '_-'
。
SPECIAL_CHARS = '_-'
string.digits + string.ascii_letters + SPECIAL_CHARS
ASCII印刷可能ファイルのランダムな文字列によるタイミング:
from inspect import getsource
from random import sample
import re
from string import printable
from timeit import timeit
pattern_single = re.compile(r'[\W]')
pattern_repeat = re.compile(r'[\W]+')
translation_tb = str.maketrans('', '', ''.join(c for c in map(chr, range(256)) if not c.isalnum()))
def generate_test_string(length):
return ''.join(sample(printable, length))
def main():
for i in range(0, 60, 10):
for test in [
lambda: ''.join(c for c in generate_test_string(i) if c.isalnum()),
lambda: ''.join(filter(str.isalnum, generate_test_string(i))),
lambda: re.sub(r'[\W]', '', generate_test_string(i)),
lambda: re.sub(r'[\W]+', '', generate_test_string(i)),
lambda: pattern_single.sub('', generate_test_string(i)),
lambda: pattern_repeat.sub('', generate_test_string(i)),
lambda: generate_test_string(i).translate(translation_tb),
]:
print(timeit(test), i, getsource(test).lstrip(' lambda: ').rstrip(',\n'), sep='\t')
if __name__ == '__main__':
main()
結果(Python 3.7):
Time Length Code
6.3716264850008880 00 ''.join(c for c in generate_test_string(i) if c.isalnum())
5.7285426190064750 00 ''.join(filter(str.isalnum, generate_test_string(i)))
8.1875841680011940 00 re.sub(r'[\W]', '', generate_test_string(i))
8.0002205439959650 00 re.sub(r'[\W]+', '', generate_test_string(i))
5.5290945199958510 00 pattern_single.sub('', generate_test_string(i))
5.4417179649972240 00 pattern_repeat.sub('', generate_test_string(i))
4.6772285089973590 00 generate_test_string(i).translate(translation_tb)
23.574712151996210 10 ''.join(c for c in generate_test_string(i) if c.isalnum())
22.829975890002970 10 ''.join(filter(str.isalnum, generate_test_string(i)))
27.210196289997840 10 re.sub(r'[\W]', '', generate_test_string(i))
27.203713296003116 10 re.sub(r'[\W]+', '', generate_test_string(i))
24.008979928999906 10 pattern_single.sub('', generate_test_string(i))
23.945240008994006 10 pattern_repeat.sub('', generate_test_string(i))
21.830899796994345 10 generate_test_string(i).translate(translation_tb)
38.731336012999236 20 ''.join(c for c in generate_test_string(i) if c.isalnum())
37.942474347000825 20 ''.join(filter(str.isalnum, generate_test_string(i)))
42.169366310001350 20 re.sub(r'[\W]', '', generate_test_string(i))
41.933375883003464 20 re.sub(r'[\W]+', '', generate_test_string(i))
38.899814646996674 20 pattern_single.sub('', generate_test_string(i))
38.636144253003295 20 pattern_repeat.sub('', generate_test_string(i))
36.201238164998360 20 generate_test_string(i).translate(translation_tb)
49.377356811004574 30 ''.join(c for c in generate_test_string(i) if c.isalnum())
48.408927293996385 30 ''.join(filter(str.isalnum, generate_test_string(i)))
53.901889764994850 30 re.sub(r'[\W]', '', generate_test_string(i))
52.130339455994545 30 re.sub(r'[\W]+', '', generate_test_string(i))
50.061149017004940 30 pattern_single.sub('', generate_test_string(i))
49.366573111998150 30 pattern_repeat.sub('', generate_test_string(i))
46.649754120997386 30 generate_test_string(i).translate(translation_tb)
63.107938601999194 40 ''.join(c for c in generate_test_string(i) if c.isalnum())
65.116287978999030 40 ''.join(filter(str.isalnum, generate_test_string(i)))
71.477421126997800 40 re.sub(r'[\W]', '', generate_test_string(i))
66.027950693998720 40 re.sub(r'[\W]+', '', generate_test_string(i))
63.315361931003280 40 pattern_single.sub('', generate_test_string(i))
62.342320287003530 40 pattern_repeat.sub('', generate_test_string(i))
58.249303059004890 40 generate_test_string(i).translate(translation_tb)
73.810345625002810 50 ''.join(c for c in generate_test_string(i) if c.isalnum())
72.593953348005020 50 ''.join(filter(str.isalnum, generate_test_string(i)))
76.048324580995540 50 re.sub(r'[\W]', '', generate_test_string(i))
75.106637657001560 50 re.sub(r'[\W]+', '', generate_test_string(i))
74.681338128997600 50 pattern_single.sub('', generate_test_string(i))
72.430461594005460 50 pattern_repeat.sub('', generate_test_string(i))
69.394243567003290 50 generate_test_string(i).translate(translation_tb)
str.maketrans
&str.translate
が最も高速ですが、すべての非ASCII文字が含まれます。
re.compile
&pattern.sub
は低速ですが、''.join
&よりも高速ですfilter
。
私が正しく理解している場合、最も簡単な方法は、多くの柔軟性を提供する正規表現を使用することです。
s = """An... essay is, generally, a piece of writing that gives the author's own
argument — but the definition is vague,
overlapping with those of a paper, an article, a pamphlet, and a short story. Essays
have traditionally been
sub-classified as formal and informal. Formal essays are characterized by "serious
purpose, dignity, logical
organization, length," whereas the informal essay is characterized by "the personal
element (self-revelation,
individual tastes and experiences, confidential manner), humor, graceful style,
rambling structure, unconventionality
or novelty of theme," etc.[1]"""
d = {} # creating empty dic
words = s.split() # spliting string and stroing in list
for word in words:
new_word = ''
for c in word:
if c.isalnum(): # checking if indiviual chr is alphanumeric or not
new_word = new_word + c
print(new_word, end=' ')
# if new_word not in d:
# d[new_word] = 1
# else:
# d[new_word] = d[new_word] +1
print(d)
この回答が役に立ったら評価してください!