Reverse string di Python

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.

Larutan

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.

Komentar (2)

@Paolo's s[::-1] tercepat; pendekatan yang lebih lambat (mungkin lebih mudah dibaca, tapi yang's diperdebatkan) adalah''.bergabung(terbalik(s)).

Komentar (4)

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'

Lagi penjelasan

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:

  1. Di Python, string yang berubah. Mengubah string tidak memodifikasi string. Itu menciptakan yang baru.

  2. 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]

A dapat dibaca pendekatan:

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))

Paling performant pendekatan:

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]

Melaksanakan sebagai Fungsi

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')

Apa yang guru anda mungkin ingin:

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.

Praktek Terbaik

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.

Timing

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.

Komentar (1)

Jawaban cepat (TL;DR)

Contoh

### example01 -------------------
mystring  =   'coup_ate_grouping'
backwards =   mystring[::-1]
print backwards

### ... or even ...
mystring  =   'coup_ate_grouping'[::-1]
print mystring

### result01 -------------------
'''
gnipuorg_eta_puoc
'''

Jawaban Rinci

Latar belakang

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()?

Masalah

  • Konteks
  • Python 2.x
  • Python 3.x
  • Skenario:
  • Pengembang ingin mengubah sebuah string
  • Transformasi ke urutan terbalik dari semua karakter

Solusi

Perangkap

  • Pengembang mungkin mengharapkan sesuatu seperti string.reverse()
  • Asli idiomatik (alias "pythonic") solusi tidak dapat dibaca untuk pengembang baru
  • Pengembang mungkin tergoda untuk melaksanakan sendiri versi string.reverse() untuk menghindari slice notasi.
  • Output dari potongan notasi dapat menjadi kontra-intuitif dalam beberapa kasus:
  • lihat misalnya, example02
  • cetak 'coup_ate_grouping'[-4:] ## => 'ping'
  • dibandingkan dengan
  • cetak 'coup_ate_grouping'[-4:-1] ## => 'pin'
  • dibandingkan dengan
  • cetak 'coup_ate_grouping'[-1] ## => 'g'
  • hasil yang berbeda dari pengindeksan pada [-1] dapat membuang beberapa pengembang off

Alasan

Python 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

### 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'

Kesimpulan

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.

Lihat juga

Komentar (0)

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"

Komentar (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:

[![enter image description here][1]][1]

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

[![enter image description here][2]][2]

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).

String Pembalikan

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

  • U: jari menunjuk ke atas
  • M: coklat pengubah
  • L: jari yang menunjuk ke kiri

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

Kode


#!/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:
Komentar (0)

1. menggunakan slice notasi

def rev_string(s): 
    return s[::-1]

2. menggunakan dibalik() fungsi

def rev_string(s): 
    return ''.join(reversed(s))

3. menggunakan rekursi

def rev_string(s): 
    if len(s) == 1:
        return s

    return s[-1] + rev_string(s[:-1])
Komentar (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'
Komentar (0)

Reverse string di python tanpa menggunakan dibalik() atau [::-1]

def reverse(test):
    n = len(test)
    x=""
    for i in range(n-1,-1,-1):
        x += test[i]
    return x
Komentar (1)
def reverse(input):
    return reduce(lambda x,y : y+x, input)
Komentar (1)
original = "string"

rev_index = original[::-1]
rev_func = list(reversed(list(original))) #nsfw

print(original)
print(rev_index)
print(''.join(rev_func))
Komentar (1)

Metode Recursive:

def reverse(s): return s[0] if len(s)==1 else s[len(s)-1] + reverse(s[0:len(s)-1])

contoh:

print(reverse("Hello!"))    #!olleH
Komentar (0)

Di sini adalah tidak mewah satu:

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!")
Komentar (0)

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.

Komentar (0)

Thats cara saya:

def reverse_string(string):
    character_list = []
    for char in string:
        character_list.append(char)
    reversed_string = ""
    for char in reversed(character_list):
        reversed_string += char
    return reversed_string
Komentar (0)
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.

Komentar (0)

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"))
Komentar (0)

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)  

Output

dlrow olleh

Referensi

Komentar (0)

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.

Komentar (0)

Ini adalah sederhana dan bermakna fungsi sebaliknya, mudah untuk memahami dan kode

def reverse_sentence(text):
    words = text.split(" ")
    reverse =""
    for word in reversed(words):
        reverse += word+ " "
    return reverse
Komentar (1)