// Python

Slicing är hela tricket: palindromer, omvändningar och off-by-one-buggar

Anthony · 8 min lästid ·

← Alla inlägg

En slice är en liten uppsättning instruktioner: var du ska börja, var du ska sluta och hur långt du ska flytta dig varje gång. När du väl kan läsa de instruktionerna slutar det att se ut som ett trick att vända på en sträng.

Börja med sequence[start:stop:step]. Starten är med. Stoppet är inte med. Utelämnar du ett värde väljer Python ett standardvärde utifrån vilket håll du rör dig åt.

Läs gränserna först

Tänk på indexen som positioner du kan besöka. Med ett positivt steg flyttar du dig åt höger tills du når stoppositionen. Du tar aldrig med elementet på själva stoppet.

slices.py
word = "terminal"
print(word[0:4])   # term
print(word[4:])    # inal
print(word[:4])    # term
print(word[1:7:2]) # emn

För en slice framåt med steget ett säger stop - start hur många element du får, så länge båda gränserna ligger inom sekvensen. Det gör word[0:4] lätt att kontrollera: fyra tecken, med start på noll.

Stoppet är en gräns, inte det sista elementet du vill behålla.

Byt riktning

Ett negativt steg går åt vänster. Med [::-1] utelämnas båda gränserna, så Python börjar på det sista elementet och fortsätter förbi det första.

reverse.py
word = "drawer"
reversed_word = word[::-1]
print(reversed_word)  # reward

Här är fällan: ett utelämnat stopp och ett uttryckligt -1 gör olika saker. Indexet -1 pekar på det sista elementet. Därför är word[:-1:-1] tomt: du står redan på stoppet som inte ska vara med.

När en baklänges slice överraskar dig, skriv ner startindexet och stoppindexet. Följ sedan stegets riktning innan du kör koden.

Gör en omvändning till en kontroll

Ett palindrom läses likadant framlänges och baklänges. För en enkel exakt kontroll jämför du den ursprungliga strängen med sin spegelbild.

palindrome.py
def is_palindrome(text):
    return text == text[::-1]

assert is_palindrome("racecar")
assert not is_palindrome("python")
assert is_palindrome("")

Bestäm vad din utmaning menar med ”likadant” innan du lägger till normalisering. Ska mellanslag räknas? Stora bokstäver? En exakt jämförelse ser dem som olika tecken. En fraskontroll kanske tar bort skiljetecken och kör casefold() först.

Låt gränsfallen göra jobbet

  • Prova en tom sträng och en sträng med ett enda tecken.
  • Prova jämn och udda längd: abba och radar.
  • Kontrollera ett värde som nästan stämmer, till exempel abca.
  • Prova ett stopp bortom slutet. Slices klipps till sekvensens gränser.

Steget noll ger ValueError. En omvänd sträng tar dessutom extra minne, eftersom slicing skapar en ny sträng. Det är helt okej för en kort utmaning; för mycket stora indata jämför du i stället tecken från båda ändarna.

Guldfärgade ledningsbanor mellan lödytor på ett kretskort
Följ en väg i taget. Foto: Vishnu Mohanan / Unsplash.

Prova utan att titta

  1. Skriv en slice som tar vartannat tecken.
  2. Vänd på ett ord och ta sedan bort dess första och sista tecken.
  3. Skriv ner resultatet innan du kör programmet.

Håll exemplen små nog att följa för hand. När utskriften skiljer sig från din gissning, kontrollera det uteslutna stoppet först.