Pythonを使用して文字列から特定の文字を削除しようとしています。これは私が今使っているコードです。残念ながら、それは文字列に対して何もしないようです。
for char in line:
if char in " ?.!/;:":
line.replace(char,'')
これを正しく行うにはどうすればよいですか?
Pythonを使用して文字列から特定の文字を削除しようとしています。これは私が今使っているコードです。残念ながら、それは文字列に対して何もしないようです。
for char in line:
if char in " ?.!/;:":
line.replace(char,'')
これを正しく行うにはどうすればよいですか?
回答:
Pythonの文字列は不変です(変更できません)。このため、の効果はline.replace(...)
、古い文字列を変更するのではなく、単に新しい文字列を作成することです。それらの文字を削除して、変数に新しい値を割り当てるには、それを再バインド(割り当て)する必要がありline
ます。
また、あなたがそれをしているやり方は、比較的遅いです。また、二重にネストされた構造を見て、少し複雑なことが起こっていることを一瞬考える熟練したpythonatorを少し混乱させる可能性もあります。
Python 2.6以降のPython 2.xバージョン*以降、代わりにを使用できますstr.translate
(ただし、Python 3の違いについては以下をお読みください)。
line = line.translate(None, '!@#$')
または正規表現置換 re.sub
import re
line = re.sub('[!@#$]', '', line)
大括弧で囲まれた文字は、文字クラスを構成します。line
そのクラスに含まれるすべての文字は、2番目のパラメーターでsub
空の文字列に置き換えられます。
Python 3では、文字列はUnicodeです。少し違う方法で翻訳する必要があります。kevpieは回答の1つに関するコメントでこれについて言及しており、のドキュメントにstr.translate
記載されています。
translate
Unicode文字列のメソッドを呼び出すときに、上記で使用した2番目のパラメーターを渡すことはできません。またNone
、最初のパラメーターとして渡すこともできません。代わりに、変換テーブル(通常は辞書)を唯一のパラメーターとして渡します。この表は、文字の順序値(つまり、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 '!@#$'})
または、次のコマンドで同じ変換テーブルを作成しますstr.maketrans
。
unicode_line = unicode_line.translate(str.maketrans('', '', '!@#$'))
*以前のPythonとの互換性のために、「null」変換テーブルを作成して、の代わりに渡すことができますNone
。
import string
line = line.translate(string.maketrans('', ''), '!@#$')
ここでstring.maketrans
は、変換テーブルを作成するために使用されます。これは、順序値0〜255の文字を含む文字列です。
line.translate
引数が1つしか取られず、最初の解決策は機能しません
line.translate({ord(i):None for i in '!@#$'})
"'"
、文字セットを記述するだけです。
notes = notes.translate({ord(i):None for i in '\"\''})
unicode_line.translate(str.maketrans('', '', '!@#$'))
。またはunicode_line.translate(dict.fromkeys(map(ord, '!@#$')))
私はここでポイントを逃していますか、それとも次のとおりですか?
string = "ab1cd1ef"
string = string.replace("1","")
print string
# result: "abcdef"
ループに入れます:
a = "a!b@c#d$"
b = "!@#$"
for char in b:
a = a.replace(char,"")
print a
# result: "abcd"
for char in b: a=a.replace(char,"")
string=string.replace("1","")
代わりにする必要があります。あなたはこれをあなたの例のループ部分で言ったが、ほとんどの人はそのような単純な質問のために最初に少し手でコードをいじるまで、あなたの答えまでそれを読むことはないだろう。
re.sub
Python 3.5以降の正規表現で簡単にre.sub('\ |\?|\.|\!|\/|\;|\:', '', line)
>>> import re
>>> line = 'Q: Do I write ;/.??? No!!!'
>>> re.sub('\ |\?|\.|\!|\/|\;|\:', '', line)
'QDoIwriteNo'
で正規表現(正規表現)、|
論理的ORと\
実際の正規表現のコマンドであるかもしれないスペースや特殊文字をエスケープします。一方sub
、置換は、この場合は空の文字列''
です。
文字列内の特定の文字のみを許可するという逆の要件については、補集合演算子で正規表現を使用できます[^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, " ?.!/;:")
文字列はPythonでは不変です。このreplace
メソッドは、置換後に新しい文字列を返します。試してください:
for char in line:
if char in " ?.!/;:":
line = line.replace(char,'')
line
。
ビルトインのフィルター機能の使用をまだ誰も推奨していなかったことに驚きました。
import operator
import string # only for the example you could use a custom string
s = "1212edjaq"
数値ではないすべてのものを除外したいとします。組み込みのフィルターメソッド「...は、ジェネレーター式(if(item)の反復可能アイテムのアイテム)に相当します」[ Python 3 Builtins:Filter ]
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"
どのようにフィルターするかわかりませんが効率の点でランク付けされるが、リスト内包などを行う場合の使用方法を知ることは良いことです。
更新
論理的には、フィルターは機能するので、リスト内包表記を使用することもできます。ラムダはプログラミング関数の世界のウォールストリートヘッジファンドマネージャーであるため、私が読んだ内容からより効率的であると考えられます。もう1つの利点は、インポートが不要なワンライナーであることです。たとえば、上記で定義したのと同じ文字列「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])
operator.contains
使っているなら使う理由はないlambda
。lambda x: operator.contains(intsList, x)
スペルを入力する必要がありますlambda x: x in intsList
。または、Cレベルのチェックを取得しようとしている場合は、intsList.__contains__
(lambda
まったく)トリックを実行します。
を使用すると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.
このタスクを実行するいくつかの可能な方法を次に示します。
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"))
PS:代わりに "?。!/ ;:"を使用します。例では母音を使用しています...そうです、 "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
したがって、この特定の入力では、attempt4が最も速いようです。
list
を作成していattempt1
て"aeiou"
、単純にするためにタプルを書き換えることができます(削除する[
と]
、リストを作成せずにジェネレーターになります)。で使い捨ての中間文字列を大量に作成し、1つのパスで使用できる場所attemt2
で正規表現の複数のアプリケーションをattempt3
使用r'[aeiou]'
します。それぞれに欠点があります-さまざまな方法を確認できるのは良いことですが、それらを適切な試行になるように修正してください
これが私の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)
dict.fromkeys(map(ord, '!@#$'))
地図の作成に使用します。
str.maketrans('', '', chars)
、ord
変換とdict
構成をすべて一度に処理します(これはとペアになるように設計されているため、意図がより明確であることは言うまでもありませんstr.translate
)。
#!/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
'
して文字列と見なすためのバックスラッシュがあります。docs.python.org/2/library/re.html
これはどう:
def text_cleanup(text):
new = ""
for i in text:
if i not in " ?.!/;:":
new += i
return new
また、関数を使用して、リストを使用して異なる種類の正規表現やその他のパターンを置き換えることもできます。これにより、正規表現、文字クラス、および本当に基本的なテキストパターンを混在させることができます。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
私が使用する私の方法はおそらく効率的には機能しないでしょうが、それは非常に単純です。スライスとフォーマットを使用して、異なる位置にある複数の文字を一度に削除できます。次に例を示します。
words = "things"
removed = "%s%s" % (words[:3], words[-1:])
これにより、「this」という単語が保持された「removed」になります。
書式設定は、印刷文字列の途中で変数を印刷する場合に非常に役立ちます。変数のデータ型が後に続く%を使用して、任意のデータ型を挿入できます。すべてのデータ型は%sを使用でき、浮動小数点(別名10進数)および整数は%dを使用できます。
スライスは、ストリングの複雑な制御に使用できます。私が入れたとき[:3]の言葉を、それは私が第四文字に(コロンは番号の前に、これは「と最初から」意味する場合)最初から文字列中のすべての文字を選択することができます(これは、第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」になります。^記号の後に指定されたものだけが表示されます。
文字列メソッドreplace
は、元の文字列を変更しません。オリジナルをそのままにし、変更されたコピーを返します。
あなたが欲しいものは次のようなものです: line = line.replace(char,'')
def replace_all(line, )for char in line:
if char in " ?.!/;:":
line = line.replace(char,'')
return line
ただし、文字が削除されるたびに新しい文字列を作成することは非常に非効率的です。代わりに以下をお勧めします:
def replace_all(line, baddies, *):
"""
The following is documentation on how to use the class,
without reference to the implementation details:
For implementation notes, please see comments begining with `#`
in the source file.
[*crickets chirp*]
"""
is_bad = lambda ch, baddies=baddies: return ch in baddies
filter_baddies = lambda ch, *, is_bad=is_bad: "" if is_bad(ch) else ch
mahp = replace_all.map(filter_baddies, line)
return replace_all.join('', join(mahp))
# -------------------------------------------------
# WHY `baddies=baddies`?!?
# `is_bad=is_bad`
# -------------------------------------------------
# Default arguments to a lambda function are evaluated
# at the same time as when a lambda function is
# **defined**.
#
# global variables of a lambda function
# are evaluated when the lambda function is
# **called**
#
# The following prints "as yellow as snow"
#
# fleece_color = "white"
# little_lamb = lambda end: return "as " + fleece_color + end
#
# # sometime later...
#
# fleece_color = "yellow"
# print(little_lamb(" as snow"))
# --------------------------------------------------
replace_all.map = map
replace_all.join = str.join
あなたはセットを使うことができます
charlist = list(set(string.digits+string.ascii_uppercase) - set('10IO'))
return ''.join([random.SystemRandom().choice(charlist) for _ in range(passlen)])
filter
ますが、関数とラムダ式の使用についてはどうでしょうかfilter(lambda ch: ch not in " ?.!/;:", line)
。かなり簡潔で効率的でもあると思います。もちろん、名前を割り当てる必要がある新しい文字列を返します。