Dzisiejsze zadanie to już chyba klasyk rozmów kwalifikacyjnych. Zobacz jak łatwo można je rozwiązać.
Napisz kod, który dla zadanego ciągu tekstowego : tekst = 'Jeśli wszyscy myślą tak samo, to ktoś nie myśli wcale'
odwróci kolejność liter we wszystkich słowach w tym tekście. Zatem tekst po zamianie będzie wyglądało następująco: "ilśeJ ycsyzsw ąlśym kat ,omas ot śotk ein ilśym elacw"
.
Najczęstsze błędy
Wielu kandydatów tworzy skomplikowane rozwiązania, które w wielu liniach modyfikują zadany tekst. Tymczasem zadanie to można rozwiązać w jednej linii kodu. Bardzo chciałem pokazać wam przykład złego rozwiązanie, jednak z przykrością stwierdzam, że nie jestem w stanie. Nie umiem i koniec. Dlatego od razu zajmiemy się poprawnym kodem i dokładnie go sobie omówimy.
Rozwiązanie
tekst = 'Jeśli wszyscy myślą tak samo, to ktoś nie myśli wcale' tekst_odwrocony = ' '.join(slowo[::-1] for slowo in tekst.split()) print(tekst_odwrocony)
Nic się nie martw jeśli nie do końca rozumiesz co tu się stało i dlaczego to działa. Zaraz krok po kroku przejdziemy przez wszystkie funkcje i kruczki użyte w tym rozwiązaniu.
Metoda split
Jest to metoda klasy str, umożliwiająca podział ciągu tekstowego na części, które zwracane są w postaci listy. Jako parametr przyjmuje znak po którym ma nastąpić podział. Zatem nasze wywołanie metody split()
powinno wyglądać następująco: tekst.split(' ')
by podzielić nasz tekst po „spacjach”. Jak pewnie zauważyłeś w naszym rozwiązaniu wywołaliśmy metodę split bez żadnych parametrów. To dlatego, że „spacja” (biały znak) jest parametrem domyślnym. Zatem dzięki metodzie split mamy już listę zawierającą wszystkie słowa z naszego tekstu. To krótki przykład jak działa split:
tekst = 'Jeśli wszyscy myślą tak samo, to ktoś nie myśli wcale' lista_slow = tekst.split() print(lista_slow)
Output:
['Jeśli', 'wszyscy', 'myślą', 'tak', 'samo,', 'to', 'ktoś', 'nie', 'myśli', 'wcale']
Odwracanie liter w wyrazie
Jak już uda nam dostać się do konkretnego słowa zapisanego w naszej liście trzeba odwrócić w nim litery. Robimy to za pomocą operatora zakresu. Operator ten może przyjąć trzy wartości [indeks początkowy : indeks końcowy : skok]
. My używamy go tak : slowo[::-1]
. Zatem czytamy go następująco. Od początku wyrazu do jego samego końca ze skokiem o wartości -1. To właśnie skok -1 robi tu robotę. Oznacza to że idziemy od końca wyrazu do jego początku, a zatem odwracamy kolejność liter.
slowo = 'wszyscy' slowo_odwrocone = slowo[::-1] print(slowo_odwrocone)
Output:
ycsyzsw
Generator składny
Wiemy już jak podzielić tekst na listę zawierającą poszczególne słowa. Wiemy też jak odwrócić kolejność liter w danym słowie. Jak przeprowadzić tą operację na każdym słowie będącym w naszej liście ? Odpowiedź jest prosta. Generator składany. Oczywiście można by tu posłużyć się zwykłą lista składna i efekt końcowy byłby taki sam. Użycie generatora jest jednak dużo schludniejszym rozwiązaniem oszczędzającym naszą pamięć.
tekst = 'Jeśli wszyscy myślą tak samo, to ktoś nie myśli wcale' generator_odwracający = (slowo[::-1] for slowo in tekst.split(' ')) print(type(generator_odwracający)) for odwrcone_slowo in generator_odwracający: print(odwrcone_slowo)
Output:
<class 'generator'> ilśeJ ycsyzsw ąlśym kat ,omas ot śotk ein ilśym elacw
Metoda join
Metoda join (również metoda klasy str) jest przeciwieństwem omawianej wcześniej metody split. Metoda split z ciągu tekstowego tworzy listę. Natomiast metoda join wywoływana na rzecz ciągu tekstowego pobiera listę (lubi inną kolekcję) i robi z niej ciąg tekstowy. Najłatwiej zobrazuje to przykład:
tekst = ['Python' ,'jest' ,'fajny'] print('XX'.join(tekst)) print(' '.join(tekst))
Output:
PythonXXjestXXfajny Python jest fajny
Jak widzisz ”string” na rzecz którego wywoła zostanie metoda join staje się separatorem. W naszym przykładzie separatorem zostanie znak spacji.
Jeszcze jedna ważna rzecz
Wprawni obserwatorzy na pewno zauważą, że w naszym wywołaniu metody join brakuje nawiasów należących do generatora składanego.
Powinno być:
tekst_odwrocony = ' '.join((slowo[::-1] for slowo in tekst.split(' ')))
Tymczasem mamy:
tekst_odwrocony = ' '.join(slowo[::-1] for slowo in tekst.split(' '))
Oba rozwiązania działają ,a nawet są sobie równoważne. Jest to kolejne udogodnienie języka Python. Jeśli mamy zamiar przekazać generator składany bezpośrednio w wywołaniu funkcji nawiasy te nie są wymagane. Ma to na celu uproszczenie zapisu.
In [41]: timeit.Timer('” „.join(tekst[::-1].split()[::-1])’, 'tekst = „ilśeJ ycsyzsw ąlśym kat ,omas ot śotk ein ilśym elacw”’).timeit()
Out[41]: 1.3349874980003733
In [42]: timeit.Timer('” „.join(x[::-1] for x in tekst.split()) ’, 'tekst = „ilśeJ ycsyzsw ąlśym kat ,omas ot śotk ein ilśym elacw”’).timeit
…: ()
Out[42]: 2.6431509399999413