回答:
どうですか:
>>> 'hello world'[::-1]
'dlrow olleh'
これは拡張スライス構文です。これは次のように機能し[begin:end:step]
ます-beginとendを残して、-1のステップを指定することにより、文字列を逆にします。
b = a.decode('utf8')[::-1].encode('utf8')
がありましたが、正しい方向に感謝します!
.decode('utf8')
必要な場合はa
、バイトではなく文字列オブジェクトを含まないことを意味します。
@Paolo s[::-1]
は最速です。より遅いアプローチ(より読みやすいかもしれませんが、議論の余地があります)は''.join(reversed(s))
です。
join
持ってとにかくリストを構築するためにサイズを取得できるようにします。''.join(list(reversed(s)))
少し速いかもしれません。
文字列の逆関数を実装する最良の方法は何ですか?
この質問に対する私自身の経験は学問的です。ただし、簡単な答えを探しているプロの場合は、次のようなスライスを使用します-1
。
>>> 'a string'[::-1]
'gnirts a'
以上の読み取り可能(ただし、低速のメソッド名の検索とイテレータを与えられたときのフォームにリストに参加事実によります)、 str.join
:
>>> ''.join(reversed('a string'))
'gnirts a'
または読みやすさと再利用性のために、スライスを関数に入れます
def reversed_string(a_string):
return a_string[::-1]
その後:
>>> reversed_string('a_string')
'gnirts_a'
学術博覧会に興味があるなら、読み続けてください。
Pythonのstrオブジェクトには組み込みの逆関数はありません。
Pythonの文字列について知っておくべきことをいくつか示します。
Pythonでは、文字列は不変です。文字列を変更しても、文字列は変更されません。新しいものを作成します。
文字列はスライス可能です。文字列をスライスすると、指定された増分で、文字列内のあるポイントから後方または前方に、別のポイントまでの新しい文字列が得られます。それらは添え字のスライス表記またはスライスオブジェクトを取ります:
string[subscript]
下付き文字は、中括弧内にコロンを含めることでスライスを作成します。
string[start:stop:step]
ブレースの外側にスライスを作成するには、スライスオブジェクトを作成する必要があります。
slice_obj = slice(start, stop, step)
string[slice_obj]
一方で''.join(reversed('foo'))
読み取り可能である、それは、文字列のメソッドを呼び出す必要がありstr.join
、むしろ比較的遅くすることができ、別の呼び出された関数、で、。これを関数に入れましょう-戻ってきます:
def reverse_string_readable_answer(string):
return ''.join(reversed(string))
逆スライスを使用する方がはるかに高速です。
'foo'[::-1]
しかし、スライスや元の作者の意図にあまり詳しくない人に、これをどのように読みやすく理解しやすくすることができるでしょうか。添え字表記の外側にスライスオブジェクトを作成して、わかりやすい名前を付け、添え字表記に渡します。
start = stop = None
step = -1
reverse_slice = slice(start, stop, step)
'foo'[reverse_slice]
これを実際に関数として実装するには、意味のある名前を使用するだけで十分意味が明確になると思います。
def reversed_string(a_string):
return a_string[::-1]
そして使い方は簡単です:
reversed_string('foo')
インストラクターがいる場合、おそらく空の文字列から始めて、古い文字列から新しい文字列を作成する必要があります。これは、whileループを使用して、純粋な構文とリテラルで実行できます。
def reverse_a_string_slowly(a_string):
new_string = ''
index = len(a_string)
while index:
index -= 1 # index = index - 1
new_string += a_string[index] # new_string = new_string + character
return new_string
文字列は不変であるため、これは理論的には不適切です。つまり、に文字を追加しているように見えるたびにnew_string
、理論的には毎回新しい文字列が作成されます。ただし、CPythonは特定のケースでこれを最適化する方法を知っています。
理論的には、リスト内の部分文字列を収集し、後でそれらを結合することをお勧めします。
def reverse_a_string_more_slowly(a_string):
new_strings = []
index = len(a_string)
while index:
index -= 1
new_strings.append(a_string[index])
return ''.join(new_strings)
ただし、以下のCPythonのタイミングでわかるように、CPythonは文字列の連結を最適化できるため、実際にはこれに時間がかかります。
タイミングは次のとおりです。
>>> a_string = 'amanaplanacanalpanama' * 10
>>> min(timeit.repeat(lambda: reverse_string_readable_answer(a_string)))
10.38789987564087
>>> min(timeit.repeat(lambda: reversed_string(a_string)))
0.6622700691223145
>>> min(timeit.repeat(lambda: reverse_a_string_slowly(a_string)))
25.756799936294556
>>> min(timeit.repeat(lambda: reverse_a_string_more_slowly(a_string)))
38.73570013046265
CPythonは文字列連結を最適化しますが、他の実装はそうではないかもしれません:
... a + = bまたはa = a + bの形式のステートメントに対して、CPythonのインプレース文字列連結の効率的な実装に依存しないでください。この最適化はCPythonでも脆弱であり(一部のタイプでのみ機能します)、refcountingを使用しない実装にはまったく存在しません。ライブラリのパフォーマンスに敏感な部分では、代わりに '' .join()フォームを使用する必要があります。これにより、さまざまな実装間で連結が線形時間で行われることが保証されます。
while
おそらくこれは読みにくいですが、とインデックスのデクリメントのベストプラクティスセクションについてはわかりません for i in range(len(a_string)-1, -1, -1):
。あなたが選択した例文字列は、あなたがそれを逆にする必要はありませんでしょう一つのケースで、あなたは:)を持っていた場合伝えることができないだろうことを、すべてのI愛のほとんどは
### example01 -------------------
mystring = 'coup_ate_grouping'
backwards = mystring[::-1]
print backwards
### ... or even ...
mystring = 'coup_ate_grouping'[::-1]
print mystring
### result01 -------------------
'''
gnipuorg_eta_puoc
'''
この回答は、@ odigityからの次の懸念に対処するために提供されています。
ワオ。パオロが提案した解決策に最初は恐れていましたが、それは最初のコメントを読んだときに感じた恐怖に後ずさりしました。私はとても混乱しているので、そのような明るいコミュニティは、非常に基本的な何かのためにそのような不可解な方法を使用することをお勧めします。なぜs.reverse()だけではないのですか?
string.reverse()
string.reverse()
を実装して、スライス表記を回避したくなるかもしれません。print 'coup_ate_grouping'[-4:] ## => 'ping'
print 'coup_ate_grouping'[-4:-1] ## => 'pin'
print 'coup_ate_grouping'[-1] ## => 'g'
[-1]
一部の開発者が遅れる可能性がありますPythonには特別な状況があります。文字列は反復可能な型です。
string.reverse()
メソッドを除外する根拠の1つは、Python開発者にこの特別な状況の力を活用するインセンティブを与えることです。
簡単に言えば、これは単に、文字列内の個々の文字を、他のプログラミング言語の配列のように、要素の順次配置の一部として簡単に操作できることを意味します。
これがどのように機能するかを理解するために、example02を確認すると、適切な概要がわかります。
### example02 -------------------
## start (with positive integers)
print 'coup_ate_grouping'[0] ## => 'c'
print 'coup_ate_grouping'[1] ## => 'o'
print 'coup_ate_grouping'[2] ## => 'u'
## start (with negative integers)
print 'coup_ate_grouping'[-1] ## => 'g'
print 'coup_ate_grouping'[-2] ## => 'n'
print 'coup_ate_grouping'[-3] ## => 'i'
## start:end
print 'coup_ate_grouping'[0:4] ## => 'coup'
print 'coup_ate_grouping'[4:8] ## => '_ate'
print 'coup_ate_grouping'[8:12] ## => '_gro'
## start:end
print 'coup_ate_grouping'[-4:] ## => 'ping' (counter-intuitive)
print 'coup_ate_grouping'[-4:-1] ## => 'pin'
print 'coup_ate_grouping'[-4:-2] ## => 'pi'
print 'coup_ate_grouping'[-4:-3] ## => 'p'
print 'coup_ate_grouping'[-4:-4] ## => ''
print 'coup_ate_grouping'[0:-1] ## => 'coup_ate_groupin'
print 'coup_ate_grouping'[0:] ## => 'coup_ate_grouping' (counter-intuitive)
## start:end:step (or start:end:stride)
print 'coup_ate_grouping'[-1::1] ## => 'g'
print 'coup_ate_grouping'[-1::-1] ## => 'gnipuorg_eta_puoc'
## combinations
print 'coup_ate_grouping'[-1::-1][-4:] ## => 'puoc'
認知的負荷スライス表記はpythonでどのように機能するかを理解することに関連付けられているが、実際の言語を学ぶことに多くの時間を投資したくないいくつかの採用や開発者のためにあまりにも多くのことがあります。
それにもかかわらず、基本的な原則が理解されれば、固定文字列操作メソッドに対するこのアプローチの力は非常に有利になる可能性があります。
そうでないと考える人のために、ラムダ関数、イテレータ、単純な1回限りの関数宣言などの代替アプローチがあります。
必要に応じて、開発者は独自のstring.reverse()メソッドを実装できますが、Pythonのこの側面の背後にある理論的根拠を理解することは良いことです。
既存の回答は、Unicode Modifiers /書記素クラスターが無視された場合にのみ正しいです。これについては後で扱いますが、最初にいくつかの反転アルゴリズムの速度を確認します。
list_comprehension : min: 0.6μs, mean: 0.6μs, max: 2.2μs
reverse_func : min: 1.9μs, mean: 2.0μs, max: 7.9μs
reverse_reduce : min: 5.7μs, mean: 5.9μs, max: 10.2μs
reverse_loop : min: 3.0μs, mean: 3.1μs, max: 6.8μs
list_comprehension : min: 4.2μs, mean: 4.5μs, max: 31.7μs
reverse_func : min: 75.4μs, mean: 76.6μs, max: 109.5μs
reverse_reduce : min: 749.2μs, mean: 882.4μs, max: 2310.4μs
reverse_loop : min: 469.7μs, mean: 577.2μs, max: 1227.6μs
リストの内包化(reversed = string[::-1]
)の時間がすべてのケースで(私のタイプミスを修正した後でも)最も低いことがわかります。
常識的に文字列を反転したい場合は、もっと複雑です。たとえば、次の文字列(茶色の指が左を指し、黄色の指が上を指している)を取ります。これらは2つの書記素ですが、3つのUnicodeコードポイントです。追加の1つはスキンモディファイヤです。
example = "👈🏾👆"
しかし、与えられた方法のいずれかでそれを逆にすると、茶色の指が上向きになり、黄色の指が左向きになります。この理由は、「茶色」のカラーモディファイアがまだ中央にあり、その前にあるものすべてに適用されるためです。だから私たちは
そして
original: LMU
reversed: UML (above solutions)
reversed: ULM (correct reversal)
Unicode書記素クラスターは、修飾子のコードポイントよりも少し複雑です。幸い、書記素を処理するためのライブラリがあります。
>>> import grapheme
>>> g = grapheme.graphemes("👈🏾👆")
>>> list(g)
['👈🏾', '👆']
したがって、正しい答えは
def reverse_graphemes(string):
g = list(grapheme.graphemes(string))
return ''.join(g[::-1])
これもはるかに遅いです:
list_comprehension : min: 0.5μs, mean: 0.5μs, max: 2.1μs
reverse_func : min: 68.9μs, mean: 70.3μs, max: 111.4μs
reverse_reduce : min: 742.7μs, mean: 810.1μs, max: 1821.9μs
reverse_loop : min: 513.7μs, mean: 552.6μs, max: 1125.8μs
reverse_graphemes : min: 3882.4μs, mean: 4130.9μs, max: 6416.2μs
#!/usr/bin/env python
import numpy as np
import random
import timeit
from functools import reduce
random.seed(0)
def main():
longstring = ''.join(random.choices("ABCDEFGHIJKLM", k=2000))
functions = [(list_comprehension, 'list_comprehension', longstring),
(reverse_func, 'reverse_func', longstring),
(reverse_reduce, 'reverse_reduce', longstring),
(reverse_loop, 'reverse_loop', longstring)
]
duration_list = {}
for func, name, params in functions:
durations = timeit.repeat(lambda: func(params), repeat=100, number=3)
duration_list[name] = list(np.array(durations) * 1000)
print('{func:<20}: '
'min: {min:5.1f}μs, mean: {mean:5.1f}μs, max: {max:6.1f}μs'
.format(func=name,
min=min(durations) * 10**6,
mean=np.mean(durations) * 10**6,
max=max(durations) * 10**6,
))
create_boxplot('Reversing a string of length {}'.format(len(longstring)),
duration_list)
def list_comprehension(string):
return string[::-1]
def reverse_func(string):
return ''.join(reversed(string))
def reverse_reduce(string):
return reduce(lambda x, y: y + x, string)
def reverse_loop(string):
reversed_str = ""
for i in string:
reversed_str = i + reversed_str
return reversed_str
def create_boxplot(title, duration_list, showfliers=False):
import seaborn as sns
import matplotlib.pyplot as plt
import operator
plt.figure(num=None, figsize=(8, 4), dpi=300,
facecolor='w', edgecolor='k')
sns.set(style="whitegrid")
sorted_keys, sorted_vals = zip(*sorted(duration_list.items(),
key=operator.itemgetter(1)))
flierprops = dict(markerfacecolor='0.75', markersize=1,
linestyle='none')
ax = sns.boxplot(data=sorted_vals, width=.3, orient='h',
flierprops=flierprops,
showfliers=showfliers)
ax.set(xlabel="Time in ms", ylabel="")
plt.yticks(plt.yticks()[0], sorted_keys)
ax.set_title(title)
plt.tight_layout()
plt.savefig("output-string.png")
if __name__ == '__main__':
main()
def rev_string(s):
return s[::-1]
def rev_string(s):
return ''.join(reversed(s))
def rev_string(s):
if len(s) == 1:
return s
return s[-1] + rev_string(s[:-1])
RecursionError: maximum recursion depth exceeded while calling a Python object
。例:rev_string("abcdef"*1000)
それを見るためのそれほど複雑ではない方法は次のようになります:
string = 'happy'
print(string)
'ハッピー'
string_reversed = string[-1::-1]
print(string_reversed)
「イッパ」
英語では[-1 ::-1]は次のように読みます。
「-1から始めて、-1のステップを踏んでいきます。」
-1
けれども、まだ不要です。
reverse()や[::-1]を使わずにPythonで文字列を逆にします
def reverse(test):
n = len(test)
x=""
for i in range(n-1,-1,-1):
x += test[i]
return x
これも興味深い方法です。
def reverse_words_1(s):
rev = ''
for i in range(len(s)):
j = ~i # equivalent to j = -(i + 1)
rev += s[j]
return rev
または類似:
def reverse_words_2(s):
rev = ''
for i in reversed(range(len(s)):
rev += s[i]
return rev
.reverse()をサポートするbyterarrayを使用したもう1つの「エキゾチック」な方法
b = bytearray('Reverse this!', 'UTF-8')
b.reverse()
b.decode('UTF-8')
生成されます:
'!siht esreveR'
def reverse(input):
return reduce(lambda x,y : y+x, input)
def reverse_string(string):
length = len(string)
temp = ''
for i in range(length):
temp += string[length - i - 1]
return temp
print(reverse_string('foo')) #prints "oof"
これは、文字列をループして、その値を逆の順序で別の文字列に割り当てることによって機能します。
ここに派手なものはありません:
def reverse(text):
r_text = ''
index = len(text) - 1
while index >= 0:
r_text += text[index] #string canbe concatenated
index -= 1
return r_text
print reverse("hello, world!")
ここに、[::-1]
またはreversed
(学習目的で)ないものがあります。
def reverse(text):
new_string = []
n = len(text)
while (n > 0):
new_string.append(text[n-1])
n -= 1
return ''.join(new_string)
print reverse("abcd")
+=
文字列を連結するために使用できますがjoin()
、高速です。
文字列を逆にする方法はたくさんありますが、楽しみのために別の方法も作成しました。このアプローチはそれほど悪くはないと思います。
def reverse(_str):
list_char = list(_str) # Create a hypothetical list. because string is immutable
for i in range(len(list_char)/2): # just t(n/2) to reverse a big string
list_char[i], list_char[-i - 1] = list_char[-i - 1], list_char[i]
return ''.join(list_char)
print(reverse("Ehsan"))
このクラスは、Pythonマジック関数を使用して文字列を反転します。
class Reverse(object):
""" Builds a reverse method using magic methods """
def __init__(self, data):
self.data = data
self.index = len(data)
def __iter__(self):
return self
def __next__(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
REV_INSTANCE = Reverse('hello world')
iter(REV_INSTANCE)
rev_str = ''
for char in REV_INSTANCE:
rev_str += char
print(rev_str)
dlrow olleh
Python 3では、文字列をインプレースで逆にすることができます。つまり、別の変数に割り当てられません。まず、文字列をリストに変換してから、reverse()
関数を利用する必要があります。
https://docs.python.org/3/tutorial/datastructures.html
def main():
my_string = ["h","e","l","l","o"]
print(reverseString(my_string))
def reverseString(s):
print(s)
s.reverse()
return s
if __name__ == "__main__":
main()
これはシンプルで意味のある逆関数であり、理解とコーディングが簡単です
def reverse_sentence(text):
words = text.split(" ")
reverse =""
for word in reversed(words):
reverse += word+ " "
return reverse
Pythonマジックなしで文字列を反転します。
>>> def reversest(st):
a=len(st)-1
for i in st:
print(st[a],end="")
a=a-1
もちろん、Pythonでは非常に豪華な1行のコードを実行できます。:)
これは、あらゆるプログラミング言語で機能する、シンプルで丸みを帯びたソリューションです。
def reverse_string(phrase):
reversed = ""
length = len(phrase)
for i in range(length):
reversed += phrase[length-1-i]
return reversed
phrase = raw_input("Provide a string: ")
print reverse_string(phrase)
リスト包括的で反転機能を使用できます。しかし、なぜこの方法がpython 3で削除されたのか理解できません。
string = [ char for char in reversed(string)]
.join
それを有効な答えにするために何かが必要です
[c for c in string]
と同じlist(string)
です。