私はPythonを使用して文字列から特定の文字を削除しようとしています。これが私が今使っているコードです。残念ながら、文字列には何もしないようです。
for char in line:
if char in " ?.!/;:":
line.replace(char,'')
どうやってこれを正しくやるの?
Pythonの文字列は 不変 です(変更することはできません)。このため、line.replace(...)
の効果は古い文字列を変更するのではなく、単に新しい文字列を作成することです。その変数を新しい値にしてそれらの文字を削除するには、 rebind (割り当て)をline
にする必要があります。
また、あなたがしているやり方は、比較的遅くなるでしょう。また、二重にネストされた構造を見て、もう少し複雑なことが起こっていると考える経験豊富なpythonatorsをやや混乱させる可能性があります。
Python 2.6以降のPython 2.xバージョン*以降では、代わりに str.translate
、)を使用できます(ただし、Python 3の相違点についてはお読みください)。
line = line.translate(None, '!@#$')
または正規表現を re.sub
に置き換える)
import re
line = re.sub('[!@#$]', '', line)
大括弧で囲まれた文字は、 文字クラス を構成します。そのクラスに含まれるline
内の文字は、sub
:空の文字列の2番目のパラメータに置き換えられます。
Python 3では、文字列はUnicodeです。あなたは少し違うように翻訳しなければならないでしょう。 kevpieはこれを コメントの1つについてはcomment で、それは str.translate
のためのドキュメントでも説明されています)で言及しています。
Unicode文字列のtranslate
メソッドを呼び出すときに、上で使用した2番目のパラメータを渡すことはできません。最初のパラメータとしてNone
、あるいはstring.maketrans
の変換テーブルを渡すこともできません。代わりに、辞書を唯一のパラメータとして渡します。この辞書は文字の 序数値 (つまり ord
)を呼び出した結果)をそれらを置き換えるべき文字の序数値にマッピングします。 None
それらが削除されるべきであることを示します。
そのため、上記のダンスをUnicode文字列で行うには、次のように呼びます。
translation_table = dict.fromkeys(map(ord, '!@#$'), None)
unicode_line = unicode_line.translate(translation_table)
ここで、 dict.fromkeys
と map
は、以下を含む辞書を簡潔に生成するために使用されます。
{ord('!'): None, ord('@'): None, ...}
もっと簡単なのは、 別の答えはそれを としているので、その場所に辞書を作ることです:
unicode_line = unicode_line.translate({ord(c): None for c in '!@#$'})
*以前のPythonsとの互換性のために、None
の代わりに渡すために "null"変換テーブルを作成することができます。
import string
line = line.translate(string.maketrans('', ''), '!@#$')
ここで、 string.maketrans
は 変換テーブル を作成するために使用されます。これは、序数が0から255の文字を含む文字列です。
私はここでその点を見逃しているのでしょうか、それとも以下のようなものですか。
>>> string = "ab1cd1ef"
>>> string.replace("1","")
'abcdef'
>>>
それをループに入れる:
>>>
>>> a = "a!b@c#d$"
>>> b = "!@#$"
>>> for char in b:
... a = a.replace(char,"")
...
>>> print a
abcd
>>>
>>> line = "abc#@!?efg12;:?"
>>> ''.join( c for c in line if c not in '?:!/;' )
'abc#@efg12'
re.sub
を使って簡単に楽しくre.sub('\ |\?|\.|\!|\/|\;|\:', '', line)
>>> import re
>>> line = 'Q: Do I write ;/.??? No!!!'
>>> re.sub('\ |\?|\.|\!|\/|\;|\:', '', line)
'QDoIwriteNo'
正規表現 (regex)では、|
は論理的なORであり、\
は実際の正規表現コマンドである可能性があるスペースおよび特殊文字をエスケープします。 sub
は置換を表します。
文字列内の only 許可特定の文字 の逆の要件については、セット補完演算子[^ABCabc]
を含む正規表現を使用できます。たとえば、ASCII文字、数字、およびハイフン以外のすべてを削除するには、次のようにします。
>>> import string
>>> import re
>>>
>>> phrase = ' There were "nine" (9) chick-peas in my pocket!!! '
>>> allow = string.letters + string.digits + '-'
>>> re.sub('[^%s]' % allow, '', phrase)
'Therewerenine9chick-peasinmypocket'
範囲内にない文字は、セットを補完することによって一致させることができます。セットの最初の文字が
'^'
の場合、セットに含まれていないすべての文字が一致します。たとえば、[^5]
は '5'以外の任意の文字と一致し、[^^]
は'^'
以外の任意の文字と一致します。^
は、セットの最初の文字ではない場合、特別な意味はありません。
質問者はほとんどそれを持っていました。 Pythonのほとんどのものと同様に、答えはあなたが思うよりも簡単です。
>>> line = "H E?.LL!/;O:: "
>>> for char in ' ?.!/;:':
... line = line.replace(char,'')
...
>>> print line
HELLO
入れ子になったif/forループを実行する必要はありませんが、各文字を個別にチェックする必要があります。
line = line.translate(None, " ?.!/;:")
>>> s = 'a1b2c3'
>>> ''.join(c for c in s if c not in '123')
'abc'
文字列はPythonでは不変です。 replace
メソッドは置換後の新しい文字列を返します。試してください:
for char in line:
if char in " ?.!/;:":
line = line.replace(char,'')
filter
を使用すると、1行だけ必要です。
line = filter(lambda char: char not in " ?.!/;:", line)
これは文字列をイテラブルとして扱い、lambda
がTrue
を返した場合はすべての文字をチェックします。
>>> help(filter) Help on built-in function filter in module __builtin__: filter(...) filter(function or None, sequence) -> list, Tuple, or string Return those items of sequence for which function(item) is true. If function is None, return the items that are true. If sequence is a Tuple or string, return the same type, else return a list.
私はビルトインを使うことをまだ誰も推薦していないことに驚きました フィルタ 関数。
import operator
import string # only for the example you could use a custom string
s = "1212edjaq"
数字ではないものすべてを除外したいとしましょう。フィルタ組み込みメソッド "...を使用すると、ジェネレータ式(function(item)内のitemのためのitem)と等価になります" [ Python 3ビルトイン: フィルタ ]
sList = list(s)
intsList = list(string.digits)
obj = filter(lambda x: operator.contains(intsList, x), sList)))
Python 3ではこれは返す
>> <filter object @ hex>
印刷された文字列を取得するには、
nums = "".join(list(obj))
print(nums)
>> "1212"
どうかわからない フィルタ 効率の面でランク付けされていますが、リスト内包表記などを行うときに使用方法を知っておくのは良いことです。
更新
論理的には、フィルタが機能するのでリスト内包表記を使用することもできますし、ラムダはプログラミング関数の世界のウォールストリートヘッジファンドマネージャであるため、これまでに読んだものより効率的です。もう一つのプラスは、それが任意の輸入を必要としないワンライナーであるということです。たとえば、上で定義したものと同じ文字列 's'を使用します。
num = "".join([i for i in s if i.isdigit()])
それでおしまい。戻り値は、元の文字列の数字であるすべての文字の文字列になります。
許容できる文字または許容できない文字の特定のリストがある場合は、リスト内包表記の 'if'部分を調整するだけで済みます。
target_chars = "".join([i for i in s if i in some_list])
あるいは、
target_chars = "".join([i for i in s if i not in some_list])
>>> # Character stripping
>>> a = '?abcd1234!!'
>>> t.lstrip('?')
'abcd1234!!'
>>> t.strip('?!')
'abcd1234'
これを実現するためのいくつかの方法があります。
def attempt1(string):
return "".join([v for v in string if v not in ("a", "e", "i", "o", "u")])
def attempt2(string):
for v in ("a", "e", "i", "o", "u"):
string = string.replace(v, "")
return string
def attempt3(string):
import re
for v in ("a", "e", "i", "o", "u"):
string = re.sub(v, "", string)
return string
def attempt4(string):
return string.replace("a", "").replace("e", "").replace("i", "").replace("o", "").replace("u", "")
for attempt in [attempt1, attempt2, attempt3, attempt4]:
print(attempt("murcielago"))
シモンズ:代わりに "?。!/ ;:"を使った例では母音を使っています...そしてそうです、 "murcielago"はスペイン語の単語でバットを言うのです。
PS2:あなたがパフォーマンスに興味があるなら、あなたはこれらの試みを次のような簡単なコードで測定することができます:
import timeit
K = 1000000
for i in range(1,5):
t = timeit.Timer(
f"attempt{i}('murcielago')",
setup=f"from __main__ import attempt{i}"
).repeat(1, K)
print(f"attempt{i}",min(t))
私の箱には、
attempt1 2.2334518376057244
attempt2 1.8806643818474513
attempt3 7.214925774955572
attempt4 1.7271184513757465
そのため、この特定のインプットでは、試行4が最も速いと思われます。
これが私のPython 2/3互換バージョンです。翻訳apiが変わったので。
def remove(str_, chars):
"""Removes each char in `chars` from `str_`.
Args:
str_: String to remove characters from
chars: String of to-be removed characters
Returns:
A copy of str_ with `chars` removed
Example:
remove("What?!?: darn;", " ?.!:;") => 'Whatdarn'
"""
try:
# Python2.x
return str_.translate(None, chars)
except TypeError:
# Python 3.x
table = {ord(char): None for char in chars}
return str_.translate(table)
リストを使用して異なる種類の正規表現や他のパターンを置き換えるために関数を使用することもできます。それにより、正規表現、文字クラス、そして本当に基本的なテキストパターンを混在させることができます。 HTMLのようなたくさんの要素を代用する必要があるとき、それは本当に役に立ちます。
*注意:Python 3.xで動作します
import re # Regular expression library
def string_cleanup(x, notwanted):
for item in notwanted:
x = re.sub(item, '', x)
return x
line = "<title>My example: <strong>A text %very% $clean!!</strong></title>"
print("Uncleaned: ", line)
# Get rid of html elements
html_elements = ["<title>", "</title>", "<strong>", "</strong>"]
line = string_cleanup(line, html_elements)
print("1st clean: ", line)
# Get rid of special characters
special_chars = ["[!@#$]", "%"]
line = string_cleanup(line, special_chars)
print("2nd clean: ", line)
関数string_cleanupでは、文字列xと不要なリストを引数として受け取ります。要素またはパターンのリスト内の各項目について、代替が必要な場合はそれが行われます。
出力:
Uncleaned: <title>My example: <strong>A text %very% $clean!!</strong></title>
1st clean: My example: A text %very% $clean!!
2nd clean: My example: A text very clean
#!/usr/bin/python
import re
strs = "how^ much for{} the maple syrup? $20.99? That's[] ricidulous!!!"
print strs
nstr = re.sub(r'[?|$|.|!|a|b]',r' ',strs)#i have taken special character to remove but any #character can be added here
print nstr
nestr = re.sub(r'[^a-zA-Z0-9 ]',r'',nstr)#for removing special character
print nestr
これはどう:
def text_cleanup(text):
new = ""
for i in text:
if i not in " ?.!/;:":
new += i
return new
あなたはあなたのstr変数を再割り当てしなければなりません:
for char in line:
if char in " ?.!/;:":
line = line.replace(char,'')
私が使用する私の方法はおそらくそれほど効率的に機能しないでしょうが、それは非常に簡単です。スライスとフォーマットを使用して、さまざまな位置にある複数の文字を一度に削除できます。これが例です:
words = "things"
removed = "%s%s" % (words[:3], words[-1:])
これは、単語 'this'を保持している '削除'になります。
書式設定 は、印刷文字列の途中で変数を印刷するのに非常に役立ちます。 % に続けて変数のデータ型を使用して、任意のデータ型を挿入できます。すべてのデータ型は %s を使用でき、float(別名小数)と整数は %d を使用できます。
スライス は、文字列の複雑な制御に使用できます。 words [:3] を入力すると、文字列の先頭(コロンは数字の前、これは '先頭から'まで)から4文字目までのすべての文字を選択できます( 4文字目を含みます。 3が4番目の位置に等しいのは、Pythonが0から始まるからです。次に、 Word [-1:] を入力すると、最後から2番目の文字が後ろに付けられます(コロンが番号の後ろ)。 -1を設定すると、Pythonは最初の文字ではなく最後の文字から数えます。繰り返しますが、Pythonは0から始まります。したがって、 Word [-1:] は基本的に、最後の2番目の文字から文字列の末尾までを意味します。
そのため、削除したい文字の前の文字とそれ以降の文字を切り取って挟むことで、不要な文字を削除できます。 ソーセージのように考えなさい。 真ん中は汚れているので、取り除きたい。私は単に私が欲しい2つの端を切り取って、次に中間に不要な部分なしでそれらをまとめました。
複数の連続した文字を削除したい場合は、[](スライス部分)内で数字を移動します。あるいは、異なる位置から複数の文字を削除したい場合は、一度に複数のスライスを一緒に挟むことができます。
例:
words = "control"
removed = "%s%s" % (words[:2], words[-2:])
削除 'クール'に等しい。
words = "impacts"
removed = "%s%s%s" % (words[1], words[3:5], words[-1])
削除 '' macs 'と同じです。
この場合、 [3:5] は、 位置 3から 位置 5の文字(最終位置の文字を除く)を意味します。
Pythonは0 から数え始めるので、覚えておく必要があります。
Reモジュールの正規表現の置換を使用できます。 ^式を使用すると、文字列から必要なものを正確に選択できます。
import re
text = "This is absurd!"
text = re.sub("[^a-zA-Z]","",text) # Keeps only Alphabets
print(text)
これに対する出力は「Thisisabsurd」になります。 ^記号の後に指定されたもののみが表示されます。
正規表現の概念を使用せずに1つ下の..
ipstring ="text with symbols!@#$^&*( ends here"
opstring=''
for i in ipstring:
if i.isalnum()==1 or i==' ':
opstring+=i
pass
print opstring
以下の方法でもうまくいく
line = "a,b,c,d,e"
alpha = list(line)
while ',' in alpha:
alpha.remove(',')
finalString = ''.join(alpha)
print(finalString)
出力>> abcde
あなたはセットを使用することができます
charlist = list(set(string.digits+string.ascii_uppercase) - set('10IO'))
return ''.join([random.SystemRandom().choice(charlist) for _ in range(passlen)])
例えば。、
os.rename(file_name, file_name.translate({ord(c): None for c in '0123456789'}))
文字列からすべての番号を削除する
再帰的分割: s =文字列; chars =削除する文字
def strip(s,chars):
if len(s)==1:
return "" if s in chars else s
return strip(s[0:int(len(s)/2)],chars) + strip(s[int(len(s)/2):len(s)],chars)
例:
print(strip("Hello!","lo")) #He!
ディレクトリ上の各ファイルに対して#、ファイル名を変更
file_list = os.listdir (r"D:\Dev\Python")
for file_name in file_list:
os.rename(file_name, re.sub(r'\d+','',file_name))
これを試してください。
def rm_char(original_str, need2rm):
''' Remove charecters in "need2rm" from "original_str" '''
return original_str.translate(str.maketrans('','',need2rm))
この方法はpython 3.5.2でうまくいきます。