Jest to rozszerzona składnia plasterka . Działa poprzez zrobienie [begin:end:step]- pozostawiając początek i koniec i określając krok -1, odwraca ciąg.
A szybki komentarz, by powiedzieć, co robi, wyjaśni to lepiej niż używanie tej wolniejszej wersji!
tburrows13
4
jest wolniejszy, ponieważ i tak joinmusi zbudować listę, aby uzyskać rozmiar. ''.join(list(reversed(s)))może być nieco szybszy.
Jean-François Fabre
Czy masz jakieś informacje na temat tego, dlaczego [:: - 1] jest najszybszy? Chciałbym nurkować głębiej.
Tanner
@Tanner [:: - 1] jest najszybszy, ponieważ nie wywołuje żadnych funkcji zewnętrznych, a raczej używa krojenia, które jest wysoce zoptymalizowane w Pythonie. '' .join (lista (odwrócona (-e))) wykonuje 3 wywołania funkcji.
hd1
217
Jaki jest najlepszy sposób implementacji funkcji odwrotnej dla ciągów?
Moje własne doświadczenia z tym pytaniem są akademickie. Jeśli jednak jesteś profesjonalistą szukającym szybkiej odpowiedzi, użyj fragmentu, który krok po kroku -1:
>>>'a string'[::-1]'gnirts a'
lub bardziej czytelnie (ale wolniej z powodu wyszukiwania nazw metod i faktu, że join tworzy listę, gdy otrzyma się iterator) str.join:
>>>''.join(reversed('a string'))'gnirts a'
lub dla czytelności i ponownego użycia, wstaw plasterek do funkcji
Jeśli jesteś zainteresowany wykładem akademickim, czytaj dalej.
W obiekcie str Pythona nie ma wbudowanej funkcji odwrotnej.
Oto kilka rzeczy na temat ciągów Python, które powinieneś wiedzieć:
W Pythonie ciągi są niezmienne . Zmiana łańcucha nie powoduje modyfikacji łańcucha. Tworzy nowy.
Struny można kroić. Przecięcie łańcucha daje nowy ciąg z jednego punktu łańcucha, do tyłu lub do przodu, do innego punktu, o podane przyrosty. Pobierają notację plasterka lub obiekt plasterka w indeksie dolnym:
string[subscript]
Indeks dolny tworzy wycinek, włączając dwukropek w nawiasy klamrowe:
string[start:stop:step]
Aby utworzyć plasterek poza nawiasami klamrowymi, musisz utworzyć obiekt plasterka:
Chociaż ''.join(reversed('foo'))jest czytelny, wymaga wywołania metody łańcuchowej str.join, na innej wywoływanej funkcji, która może być względnie wolna. Umieśćmy to w funkcji - wrócimy do tego:
Znacznie szybsze jest stosowanie odwrotnego wycinka:
'foo'[::-1]
Ale w jaki sposób możemy uczynić to bardziej czytelnym i zrozumiałym dla osoby mniej obeznanej z wycinkami lub intencjami oryginalnego autora? Utwórzmy obiekt wycinka poza notacją indeksu dolnego, nadajmy mu opisową nazwę i przekażmy go notacji indeksu dolnego.
Jeśli masz instruktora, prawdopodobnie chcą, abyś zaczął od pustego łańcucha i zbudował nowy łańcuch ze starego. Możesz to zrobić przy użyciu czystej składni i literałów za pomocą pętli 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 + characterreturn new_string
Jest to teoretycznie złe, ponieważ pamiętaj, że ciągi są niezmienne - więc za każdym razem, gdy wygląda na to, że dodajesz do siebie znak new_string, teoretycznie za każdym razem tworzy się nowy ciąg! Jednak CPython wie, jak to zoptymalizować w niektórych przypadkach, z których ten trywialny przypadek jest jednym.
Najlepsze praktyki
Teoretycznie lepiej jest zebrać swoje podciągi na liście i dołączyć do nich później:
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)
Jednak, jak zobaczymy poniżej, dla CPython, tak naprawdę trwa to dłużej, ponieważ CPython może zoptymalizować konkatenację łańcucha.
CPython optymalizuje konkatenację łańcuchów, podczas gdy inne implementacje mogą nie :
... nie polegaj na efektywnej implementacji CPython w miejscu łączenia konkatenacji ciągów dla instrukcji w postaci a + = b lub a = a + b. Ta optymalizacja jest krucha nawet w CPython (działa tylko dla niektórych typów) i nie jest wcale obecna w implementacjach, które nie używają przeliczania. W wrażliwych na wydajność częściach biblioteki należy zamiast tego użyć formularza .join (). Zapewni to, że konkatenacja nastąpi w czasie liniowym w różnych implementacjach.
Uwielbiam tę odpowiedź, wyjaśnienia na temat optymalizacji, czytelność a optymalizacja, wskazówki na temat tego, czego chce nauczyciel. Nie jestem pewien co do sekcji najlepszych praktyk z whilei zmniejszanie wskaźnika, choć być może jest to mniej czytelny: for i in range(len(a_string)-1, -1, -1): . Przede wszystkim kocham, że przykład ciąg wybrałeś jest jeden przypadek, w którym nigdy nie trzeba go odwrócić, i nie będzie w stanie powiedzieć, czy miałeś :)
Ta odpowiedź ma na celu zaradzenie następującym obawom @odigity:
Łał. Na początku przeraziło mnie rozwiązanie zaproponowane przez Paolo, ale zajęło to miejsce z przerażeniem, które odczułem po przeczytaniu pierwszego komentarza: „To bardzo pytoniczne. Dobra robota!” Jestem tak zaniepokojony, że tak błyskotliwa społeczność myśli o użyciu tak tajemniczych metod dla czegoś tak podstawowego, to dobry pomysł. Dlaczego nie jest to po prostu s.reverse ()?
Problem
Kontekst
Python 2.x
Python 3.x
Scenariusz:
Deweloper chce przekształcić ciąg
Transformacja polega na odwróceniu kolejności wszystkich znaków
Deweloper może oczekiwać czegoś takiego string.reverse()
Natywne rozwiązanie idiomatyczne ( znane również jako „ pythonic ”) może nie być czytelne dla nowszych programistów
Deweloper może mieć pokusę, aby wdrożyć własną wersję, string.reverse()aby uniknąć notacji plastra.
W niektórych przypadkach zapis notacji może być sprzeczny z intuicją:
patrz np. example02
print 'coup_ate_grouping'[-4:] ## => 'ping'
w porównaniu do
print 'coup_ate_grouping'[-4:-1] ## => 'pin'
w porównaniu do
print 'coup_ate_grouping'[-1] ## => 'g'
różne wyniki indeksowania [-1]mogą zniechęcić niektórych programistów
Racjonalne uzasadnienie
Python ma szczególną okoliczność, o której należy pamiętać: ciąg znaków jest typem iterowalnym .
Jednym z powodów wykluczenia string.reverse()metody jest zachęcenie programistów python do wykorzystania siły tej szczególnej okoliczności.
Upraszczając, oznacza to po prostu, że każdy pojedynczy znak w ciągu może być łatwo obsługiwany jako część sekwencyjnego układu elementów, podobnie jak tablice w innych językach programowania.
Aby zrozumieć, jak to działa, przejrzyj przykład 02, aby uzyskać dobry przegląd.
Ładunek poznawczy związany ze zrozumieniem, jak działa w notacji plasterka python rzeczywiście mogą być zbyt wiele dla niektórych podmiotów przyjmujących i programistów, którzy nie chcą inwestować dużo czasu w nauce języka.
Niemniej jednak, po zrozumieniu podstawowych zasad, siła tego podejścia w stosunku do ustalonych metod manipulacji strunami może być całkiem korzystna.
Dla tych, którzy myślą inaczej, istnieją alternatywne podejścia, takie jak funkcje lambda, iteratory lub proste deklaracje funkcji jednorazowych.
W razie potrzeby programista może wdrożyć własną metodę string.reverse (), jednak dobrze jest zrozumieć uzasadnienie tego aspektu python.
Istniejące odpowiedzi są poprawne tylko wtedy, gdy ignorowane są modyfikatory Unicode / klastry grafemów. Zajmę się tym później, ale najpierw przyjrzyjmy się prędkości niektórych algorytmów odwracania:
Widać, że czas na zrozumienie listy ( reversed = string[::-1]) jest we wszystkich przypadkach zdecydowanie najniższy (nawet po poprawieniu mojej literówki).
Ale jeśli odwrócisz jedną z podanych metod, dostaniesz brązowy palec skierowany w górę , żółty palec skierowany w lewo . Powodem tego jest to, że „brązowy” modyfikator koloru jest nadal na środku i jest stosowany do wszystkiego, co jest przed nim. Więc mamy
Musisz obejrzeć rozwiązanie rekurencyjne, jeśli łańcuch ma przyzwoitą długość, na którą się natkniesz RecursionError: maximum recursion depth exceeded while calling a Python object. Np .:rev_string("abcdef"*1000)
Adam Parkin,
9
Mniej kłopotliwym sposobem spojrzenia na to byłoby:
Kliknąłem upvote, ponieważ podoba mi się to wyrażenie lambda. Niestety, jest to najmniej wydajne rozwiązanie ze wszystkich wymienionych powyżej (test: Gist palindrome.py )
oski86
2
original ="string"
rev_index = original[::-1]
rev_func = list(reversed(list(original)))#nsfwprint(original)print(rev_index)print(''.join(rev_func))
Chociaż ten kod może odpowiedzieć na pytanie, lepiej wyjaśnić, jak rozwiązać problem i podać kod jako przykład lub odniesienie. Odpowiedzi zawierające tylko kod mogą być mylące i pozbawione kontekstu.
Robert Columbia,
1
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"
Działa to poprzez zapętlanie łańcucha i przypisywanie jego wartości w odwrotnej kolejności do innego łańcucha.
Wszystkie powyższe rozwiązania są idealne, ale jeśli próbujemy odwrócić ciąg za pomocą pętli for w pythonie, będzie to nieco trudne, więc oto jak możemy odwrócić ciąg za pomocą pętli
string ="hello,world"for i in range(-1,-len(string)-1,-1):print(string[i],end=(" "))
Istnieje wiele sposobów na odwrócenie łańcucha, ale stworzyłem też inny dla zabawy. Myślę, że to podejście nie jest takie złe.
def reverse(_str):
list_char = list(_str)# Create a hypothetical list. because string is immutablefor 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"))
W Pythonie 3 możesz odwrócić ciąg w miejscu, co oznacza, że nie zostanie on przypisany do innej zmiennej. Najpierw musisz przekonwertować ciąg na listę, a następnie użyć reverse()funkcji.
Chociaż może to odpowiedzieć na pytanie autora, brakuje w nim niektórych wyjaśnień i / lub linków do dokumentacji. Fragmenty surowego kodu nie są bardzo pomocne bez niektórych fraz wokół nich. Bardzo pomocne może się okazać, jak napisać dobrą odpowiedź . Edytuj swoją odpowiedź.
cholery
-3
Oto po prostu:
drukuj „loremipsum” [- 1 :: - 1]
a niektóre logicznie:
def str_reverse_fun():
empty_list =[]
new_str ='loremipsum'
index = len(new_str)while index:
index = index -1
empty_list.append(new_str[index])return''.join(empty_list)print str_reverse_fun()
Drukowanie łańcucha w odwrotnej kolejności jest czymś innym niż odwracanie łańcucha
Martin Thoma,
-5
Jasne, w Pythonie możesz robić bardzo fantazyjne 1-liniowe rzeczy. :)
Oto proste, wszechstronne rozwiązanie, które może działać w dowolnym języku programowania.
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)
Odpowiedzi:
Co powiesz na:
Jest to rozszerzona składnia plasterka . Działa poprzez zrobienie
[begin:end:step]
- pozostawiając początek i koniec i określając krok -1, odwraca ciąg.źródło
b = a.decode('utf8')[::-1].encode('utf8')
ale dziękuję za właściwy kierunek!.decode('utf8')
jest to wymagane, oznacza to, żea
nie zawiera żadnych ciągów znaków, a raczej bajtów.@ Paolo's
s[::-1]
jest najszybszy; wolniejsze podejście (może bardziej czytelne, ale to dyskusyjne)''.join(reversed(s))
.źródło
join
musi zbudować listę, aby uzyskać rozmiar.''.join(list(reversed(s)))
może być nieco szybszy.Moje własne doświadczenia z tym pytaniem są akademickie. Jeśli jednak jesteś profesjonalistą szukającym szybkiej odpowiedzi, użyj fragmentu, który krok po kroku
-1
:lub bardziej czytelnie (ale wolniej z powodu wyszukiwania nazw metod i faktu, że join tworzy listę, gdy otrzyma się iterator)
str.join
:lub dla czytelności i ponownego użycia, wstaw plasterek do funkcji
i wtedy:
Dłuższe wyjaśnienie
Jeśli jesteś zainteresowany wykładem akademickim, czytaj dalej.
Oto kilka rzeczy na temat ciągów Python, które powinieneś wiedzieć:
W Pythonie ciągi są niezmienne . Zmiana łańcucha nie powoduje modyfikacji łańcucha. Tworzy nowy.
Struny można kroić. Przecięcie łańcucha daje nowy ciąg z jednego punktu łańcucha, do tyłu lub do przodu, do innego punktu, o podane przyrosty. Pobierają notację plasterka lub obiekt plasterka w indeksie dolnym:
Indeks dolny tworzy wycinek, włączając dwukropek w nawiasy klamrowe:
Aby utworzyć plasterek poza nawiasami klamrowymi, musisz utworzyć obiekt plasterka:
Czytelne podejście:
Chociaż
''.join(reversed('foo'))
jest czytelny, wymaga wywołania metody łańcuchowejstr.join
, na innej wywoływanej funkcji, która może być względnie wolna. Umieśćmy to w funkcji - wrócimy do tego:Najbardziej wydajne podejście:
Znacznie szybsze jest stosowanie odwrotnego wycinka:
Ale w jaki sposób możemy uczynić to bardziej czytelnym i zrozumiałym dla osoby mniej obeznanej z wycinkami lub intencjami oryginalnego autora? Utwórzmy obiekt wycinka poza notacją indeksu dolnego, nadajmy mu opisową nazwę i przekażmy go notacji indeksu dolnego.
Implementuj jako funkcję
Aby faktycznie zaimplementować to jako funkcję, myślę, że jest to semantycznie wystarczająco jasne, aby po prostu użyć opisowej nazwy:
A użycie jest po prostu:
Czego prawdopodobnie chce twój nauczyciel:
Jeśli masz instruktora, prawdopodobnie chcą, abyś zaczął od pustego łańcucha i zbudował nowy łańcuch ze starego. Możesz to zrobić przy użyciu czystej składni i literałów za pomocą pętli while:
Jest to teoretycznie złe, ponieważ pamiętaj, że ciągi są niezmienne - więc za każdym razem, gdy wygląda na to, że dodajesz do siebie znak
new_string
, teoretycznie za każdym razem tworzy się nowy ciąg! Jednak CPython wie, jak to zoptymalizować w niektórych przypadkach, z których ten trywialny przypadek jest jednym.Najlepsze praktyki
Teoretycznie lepiej jest zebrać swoje podciągi na liście i dołączyć do nich później:
Jednak, jak zobaczymy poniżej, dla CPython, tak naprawdę trwa to dłużej, ponieważ CPython może zoptymalizować konkatenację łańcucha.
Czasy
Oto czasy:
CPython optymalizuje konkatenację łańcuchów, podczas gdy inne implementacje mogą nie :
źródło
while
i zmniejszanie wskaźnika, choć być może jest to mniej czytelny:for i in range(len(a_string)-1, -1, -1):
. Przede wszystkim kocham, że przykład ciąg wybrałeś jest jeden przypadek, w którym nigdy nie trzeba go odwrócić, i nie będzie w stanie powiedzieć, czy miałeś :)Szybka odpowiedź (TL; DR)
Przykład
Szczegółowa odpowiedź
tło
Ta odpowiedź ma na celu zaradzenie następującym obawom @odigity:
Problem
Rozwiązanie
Pułapki
string.reverse()
string.reverse()
aby uniknąć notacji plastra.print 'coup_ate_grouping'[-4:] ## => 'ping'
print 'coup_ate_grouping'[-4:-1] ## => 'pin'
print 'coup_ate_grouping'[-1] ## => 'g'
[-1]
mogą zniechęcić niektórych programistówRacjonalne uzasadnienie
Python ma szczególną okoliczność, o której należy pamiętać: ciąg znaków jest typem iterowalnym .
Jednym z powodów wykluczenia
string.reverse()
metody jest zachęcenie programistów python do wykorzystania siły tej szczególnej okoliczności.Upraszczając, oznacza to po prostu, że każdy pojedynczy znak w ciągu może być łatwo obsługiwany jako część sekwencyjnego układu elementów, podobnie jak tablice w innych językach programowania.
Aby zrozumieć, jak to działa, przejrzyj przykład 02, aby uzyskać dobry przegląd.
Przykład 02
Wniosek
Ładunek poznawczy związany ze zrozumieniem, jak działa w notacji plasterka python rzeczywiście mogą być zbyt wiele dla niektórych podmiotów przyjmujących i programistów, którzy nie chcą inwestować dużo czasu w nauce języka.
Niemniej jednak, po zrozumieniu podstawowych zasad, siła tego podejścia w stosunku do ustalonych metod manipulacji strunami może być całkiem korzystna.
Dla tych, którzy myślą inaczej, istnieją alternatywne podejścia, takie jak funkcje lambda, iteratory lub proste deklaracje funkcji jednorazowych.
W razie potrzeby programista może wdrożyć własną metodę string.reverse (), jednak dobrze jest zrozumieć uzasadnienie tego aspektu python.
Zobacz też
źródło
Istniejące odpowiedzi są poprawne tylko wtedy, gdy ignorowane są modyfikatory Unicode / klastry grafemów. Zajmę się tym później, ale najpierw przyjrzyjmy się prędkości niektórych algorytmów odwracania:
Widać, że czas na zrozumienie listy (
reversed = string[::-1]
) jest we wszystkich przypadkach zdecydowanie najniższy (nawet po poprawieniu mojej literówki).Odwrócenie ciągu
Jeśli naprawdę chcesz odwrócić ciąg znaków w zdrowym znaczeniu, jest to DROGA bardziej skomplikowane. Na przykład weź następujący ciąg ( brązowy palec skierowany w lewo , żółty palec skierowany w górę ). To są dwa grafemy, ale 3 punkty kodu Unicode. Dodatkowym jest modyfikator skórki .
Ale jeśli odwrócisz jedną z podanych metod, dostaniesz brązowy palec skierowany w górę , żółty palec skierowany w lewo . Powodem tego jest to, że „brązowy” modyfikator koloru jest nadal na środku i jest stosowany do wszystkiego, co jest przed nim. Więc mamy
i
Klastry Grapheme Unicode są nieco bardziej skomplikowane niż tylko punkty kodu modyfikatora. Na szczęście istnieje biblioteka do obsługi grafemów :
i stąd poprawna odpowiedź byłaby
który również jest zdecydowanie najwolniejszy:
Kod
źródło
1. używając notacji plastra
2. za pomocą funkcji reverse ()
3. za pomocą rekurencji
źródło
RecursionError: maximum recursion depth exceeded while calling a Python object
. Np .:rev_string("abcdef"*1000)
Mniej kłopotliwym sposobem spojrzenia na to byłoby:
W języku angielskim [-1 :: - 1] brzmi:
źródło
-1
nadal jest to niepotrzebne.Odwróć ciąg znaków w pythonie bez użycia reverse () lub [:: - 1]
źródło
To także ciekawy sposób:
lub podobne:
Kolejny bardziej „egzotyczny” sposób użycia byterarray, który obsługuje .reverse ()
będzie produkować:
źródło
źródło
źródło
Działa to poprzez zapętlanie łańcucha i przypisywanie jego wartości w odwrotnej kolejności do innego łańcucha.
źródło
Oto wymyślny:
źródło
Oto jeden bez
[::-1]
lubreversed
(do celów uczenia się):możesz użyć
+=
do konkatenacji ciągów, alejoin()
jest on szybszy.źródło
Metoda rekurencyjna:
przykład:
źródło
Wszystkie powyższe rozwiązania są idealne, ale jeśli próbujemy odwrócić ciąg za pomocą pętli for w pythonie, będzie to nieco trudne, więc oto jak możemy odwrócić ciąg za pomocą pętli
Mam nadzieję, że ten będzie dla kogoś pomocny.
źródło
To jest mój sposób:
źródło
Istnieje wiele sposobów na odwrócenie łańcucha, ale stworzyłem też inny dla zabawy. Myślę, że to podejście nie jest takie złe.
źródło
Ta klasa używa magicznych funkcji Pythona do odwracania łańcucha:
Wynik
Odniesienie
źródło
W Pythonie 3 możesz odwrócić ciąg w miejscu, co oznacza, że nie zostanie on przypisany do innej zmiennej. Najpierw musisz przekonwertować ciąg na listę, a następnie użyć
reverse()
funkcji.https://docs.python.org/3/tutorial/datastructures.html
źródło
Jest to prosta i znacząca funkcja odwrotna, łatwa do zrozumienia i kodowania
źródło
Oto po prostu:
drukuj „loremipsum” [- 1 :: - 1]
a niektóre logicznie:
wynik:
muspimerol
źródło
Odwróć ciąg bez magii pytona.
źródło
Jasne, w Pythonie możesz robić bardzo fantazyjne 1-liniowe rzeczy. :)
Oto proste, wszechstronne rozwiązanie, które może działać w dowolnym języku programowania.
źródło
WYNIK :
źródło
Możesz użyć funkcji odwróconej z pełną listą. Ale nie rozumiem, dlaczego ta metoda została wyeliminowana w Pythonie 3, była niepotrzebnie.
źródło
.join
czegoś lub czegoś, aby była to poprawna odpowiedź[c for c in string]
jest równoznaczne zlist(string)
.