Tidak ada built in reverse
fungsi untuk Python's str
objek. Apa adalah cara terbaik untuk menerapkan metode ini?
Jika memasok sangat ringkas jawaban, jelaskan efisiensi. Misalnya, apakah str
objek dikonversi ke objek yang berbeda, dll.
Bagaimana tentang:
>>> 'hello world'[::-1]
'dlrow olleh'
Ini adalah extended slice sintaks. Ia bekerja dengan melakukan [mulai:end:step]
- dengan meninggalkan begin dan end off dan menentukan langkah -1, itu membalik string.
Apa adalah cara terbaik untuk melaksanakan fungsi terbalik untuk string?
Pengalaman saya sendiri dengan pertanyaan ini adalah akademik. Namun, jika anda're pro mencari jawaban cepat, gunakan sepotong bahwa langkah-langkah dengan -1
:
>>> 'a string'[::-1]
'gnirts a'
atau lebih readably (tapi lebih lambat karena metode pencarian nama dan fakta yang bergabung membentuk daftar ketika diberikan sebuah iterator), str.bergabung
:
>>> ''.join(reversed('a string'))
'gnirts a'
atau untuk dibaca dan usabilitas, menempatkan sepotong di fungsi
def reversed_string(a_string):
return a_string[::-1]
dan kemudian:
>>> reversed_string('a_string')
'gnirts_a'
Jika anda're tertarik pada akademik eksposisi, silahkan terus membaca.
tidak Ada built-in reverse function di Python's str objek.
Berikut ini adalah beberapa hal tentang Python's string yang anda harus tahu:
Di Python, string yang berubah. Mengubah string tidak memodifikasi string. Itu menciptakan yang baru.
String yang dapat diiris. Mengiris string memberi anda sebuah string baru dari satu titik dalam string, belakang atau ke depan, ke titik yang lain, dengan diberikan bertahap. Mereka mengambil sepotong notasi atau sepotong objek dalam subskrip:
string[subscript]
Subskrip menciptakan sepotong oleh termasuk usus besar dalam kawat gigi:
string[start:stop:step]
Untuk membuat sepotong luar kawat gigi, anda'akan perlu untuk membuat irisan objek:
slice_obj = slice(start, stop, step)
string[slice_obj]
Sementara''.bergabung(terbalik('foo'))
dapat dibaca, hal ini membutuhkan memanggil string metode, str.bergabung
, yang lain disebut fungsi, yang dapat menjadi agak relatif lambat. Let's menempatkan ini dalam fungsi - kita'akan datang kembali untuk itu:
def reverse_string_readable_answer(string):
return ''.join(reversed(string))
Jauh lebih cepat adalah dengan menggunakan reverse slice:
'foo'[::-1]
Tapi bagaimana kita bisa membuat ini lebih mudah dibaca dan dimengerti oleh seseorang yang kurang akrab dengan irisan atau maksud dari penulis asli? Let's membuat irisan objek di luar subskrip notasi, memberikan nama deskriptif, dan menyebarkannya ke subskrip notasi.
start = stop = None
step = -1
reverse_slice = slice(start, stop, step)
'foo'[reverse_slice]
Untuk benar-benar menerapkan ini sebagai fungsi, saya pikir itu adalah semantik yang jelas cukup untuk hanya menggunakan nama deskriptif:
def reversed_string(a_string):
return a_string[::-1]
Dan penggunaan sederhana:
reversed_string('foo')
Jika anda memiliki instruktur, mereka mungkin ingin anda untuk memulai dengan string kosong, dan membangun sebuah string baru dari yang lama. Anda dapat melakukan ini dengan murni sintaks dan literal menggunakan while loop:
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
Ini adalah secara teoritis buruk karena, ingat, string yang abadi - sehingga setiap waktu di mana terlihat seperti anda're menambahkan karakter ke new_string
, it's secara teoritis membuat string baru setiap waktu! Namun, CPython tahu bagaimana untuk mengoptimalkan ini dalam kasus-kasus tertentu, dari yang sepele ini kasus adalah salah satu.
Secara teoritis lebih baik adalah untuk mengambil substring dalam sebuah daftar, dan bergabung dengan mereka nanti:
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)
Namun, seperti yang akan kita lihat dalam waktu di bawah ini untuk CPython, ini benar-benar membutuhkan waktu lebih lama, karena CPython dapat mengoptimalkan rangkaian string.
Berikut ini adalah timing:
>>> 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 mengoptimalkan rangkaian string, sedangkan implementasi lainnya semoga tidak:
... tidak bergantung pada CPython's efisien pelaksanaan di tempat-string rangkaian untuk laporan dalam bentuk a += b atau a = a + b . Optimasi ini rapuh bahkan di CPython (ini hanya bekerja untuk beberapa jenis) dan isn't hadir di semua implementasi yang don't menggunakan refcounting. Kinerja bagian-bagian sensitif dari perpustakaan, the ''.join() formulir harus digunakan sebagai gantinya. Ini akan memastikan bahwa rangkaian terjadi dalam waktu linier di berbagai implementasi.
### example01 -------------------
mystring = 'coup_ate_grouping'
backwards = mystring[::-1]
print backwards
### ... or even ...
mystring = 'coup_ate_grouping'[::-1]
print mystring
### result01 -------------------
'''
gnipuorg_eta_puoc
'''
Jawaban ini disediakan untuk anda, berikut kekhawatiran dari @odigity:
Wow. Saya merasa ngeri dengan solusi Paolo diusulkan, tapi yang mengambil kursi kembali ke kengerian yang saya rasakan setelah membaca pertama komentar: "Yang's sangat pythonic. Good job!" aku'm jadi terganggu seperti yang terang masyarakat berpikir menggunakan samar metode untuk sesuatu yang begitu dasar adalah ide yang baik. Mengapa isn't itu hanya s.reverse()?
string.reverse()
string.reverse()
untuk menghindari slice notasi.cetak 'coup_ate_grouping'[-4:] ## => 'ping'
cetak 'coup_ate_grouping'[-4:-1] ## => 'pin'
cetak 'coup_ate_grouping'[-1] ## => 'g'
[-1]
dapat membuang beberapa pengembang offPython memiliki keadaan khusus yang harus diperhatikan: string adalah sebuah iterable jenis.
Salah satu alasan untuk mengecualikan string.reverse()
metode adalah untuk memberikan pengembang python insentif untuk memanfaatkan kekuatan ini keadaan khusus.
Dalam istilah sederhana, ini berarti setiap karakter dalam string dapat dengan mudah dioperasikan sebagai bagian dari susunan berurutan dari unsur-unsur, seperti array di bahasa pemrograman yang lain.
Untuk memahami bagaimana hal ini bekerja, meninjau example02 dapat memberikan gambaran yang baik.
### 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'
The beban kognitif terkait dengan pemahaman bagaimana slice notasi bekerja di python mungkin memang terlalu banyak untuk beberapa pengguna dan pengembang yang tidak ingin menginvestasikan banyak waktu dalam belajar bahasa.
Namun demikian, sekali-prinsip dasar yang dipahami, kekuatan dari pendekatan ini lebih dari fixed string manipulasi metode ini dapat cukup menguntungkan.
Bagi mereka yang berpikir sebaliknya, ada alternatif pendekatan, seperti lambda fungsi, iterator, atau sederhana satu-off deklarasi fungsi.
Jika diinginkan, pengembang dapat melaksanakan sendiri string.reverse() metode, namun itu lebih baik untuk memahami alasan di balik ini aspek python.
Yang lebih membingungkan cara untuk melihat itu akan menjadi:
string = 'happy'
print(string)
'selamat'
string_reversed = string[-1::-1]
print(string_reversed)
'yppah'
Dalam bahasa inggris [-1::-1] berbunyi sebagai:
"Mulai dari -1, pergi semua jalan, mengambil langkah-langkah -1"
Ada jawaban hanya benar jika Unicode Pengubah / grafem cluster diabaikan. I'll berurusan dengan itu nanti, tapi pertama-tama melihat pada kecepatan beberapa pembalikan algoritma:
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
Anda dapat melihat bahwa waktu untuk daftar pemahaman (dibalik = string[::-1]
) dalam semua kasus jauh terendah (bahkan setelah saya memperbaiki typo).
Jika anda benar-benar ingin membalikkan string dalam arti umum, itu adalah CARA yang lebih rumit. Misalnya, mengambil string berikut (coklat jari yang menunjuk ke kiri, kuning jari menunjuk ke atas). Mereka adalah dua grafem, tapi 3 kode unicode poin. Tambahan satu adalah skin modifier.
example = "👈🏾👆"
Tapi jika anda terbalik dengan apa yang diberikan metode, anda mendapatkan coklat jari menunjuk ke atas, kuning jari yang menunjuk ke kiri. Alasan untuk ini adalah bahwa "brown" warna pengubah masih di tengah dan akan diterapkan untuk apa pun sebelum itu. Jadi kita memiliki
dan
original: LMU
reversed: UML (above solutions)
reversed: ULM (correct reversal)
Unicode Grapheme Cluster adalah sedikit lebih rumit dari sekedar pengubah kode poin. Untungnya, ada sebuah perpustakaan untuk penanganan grafem:
>>> import grapheme
>>> g = grapheme.graphemes("👈🏾👆")
>>> list(g)
['👈🏾', '👆']
dan oleh karena itu jawaban yang benar akan
def reverse_graphemes(string):
g = list(grapheme.graphemes(string))
return ''.join(g[::-1])
yang juga adalah jauh paling lambat:
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])
Ini juga merupakan cara yang menarik:
def reverse_words_1(s):
rev = ''
for i in range(len(s)):
j = ~i # equivalent to j = -(i + 1)
rev += s[j]
return rev
atau serupa:
def reverse_words_2(s):
rev = ''
for i in reversed(range(len(s)):
rev += s[i]
return rev
Lain lagi 'eksotik' cara menggunakan byterarray yang mendukung .reverse()
b = bytearray('Reverse this!', 'UTF-8')
b.reverse()
b.decode('UTF-8')
akan menghasilkan:
'!siht esreveR'
Semua solusi di atas adalah sempurna tetapi jika kita mencoba untuk membalikkan string dengan menggunakan loop for di python akan menjadi sedikit rumit, jadi di sini adalah bagaimana kita bisa mengembalikan string dengan menggunakan for loop
string ="hello,world"
for i in range(-1,-len(string)-1,-1):
print (string[i],end=(" "))
Saya berharap yang satu ini akan sangat membantu bagi seseorang.
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"
Ini bekerja dengan perulangan melalui sebuah string dan menetapkan nilai-nilai dalam urutan terbalik dengan string lain.
Ada banyak cara untuk membalikkan string tapi saya juga membuat satu sama lain hanya untuk bersenang-senang. Saya pikir pendekatan ini tidak seburuk itu.
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"))
Kelas ini menggunakan python sihir fungsi untuk membalikkan string:
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
Berikut adalah salah satu tanpa [::-1]
atau terbalik
(untuk tujuan pembelajaran):
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")
anda dapat menggunakan +=
untuk menggabungkan string tapi join()
lebih cepat.