Unikati
Testi
Testi: testi-unikati.py
Naloga
Napiši funkcijo
unikati(s), ki prejme seznamsin vrne seznam, v kateri so vsi elementisbrez njihovih ponovitev. Vrstni red elementov mora biti enak vrstnemu redu njihovih prvih pojavitev. Klicunikati([5, 4, 1, 4, 4, 4, 4, 4, 3, 1])vrne[5, 4, 1, 3].Napiši funkcijo
ocisti(s), ki iz seznamaspobriše ponovitve elementov. Če imamos = [5, 4, 1, 4, 4, 4, 4, 4, 3, 1], naj klicocisti(s)spremenisv[5, 4, 1, 3].Napiši funkcijo
podvoji(s), ki spremeni seznamstako, da se vsak element v njem ponovi dvakrat zapored. Če imamos = [5, 1, 3, 1, 4], bo po klicupodvoji(s)seznamsenak[5, 5, 1, 1, 3, 3, 1, 1, 4, 4].
Vse funkcije naj delajo s poljubnimi tipi elementov v seznamih, ne le s števili.
Rešitve
Unikati
Funkcijo unikati smo že pisali. Pa ponovimo:
def unikati(s):
t = []
for i in range(len(s)):
if s[i] not in s[:i]:
t.append(s[i])
return t
Če i-tega elementa na najdemo med prvimi i-timi, ga dodamo v novi seznam t, ki ga na koncu vrnemo.
Ker gre poštenemu človeku na živce, da dela zanko prek i in range(len(s)) in potem pobira i-ti element (s[i]), bi si želel imeti zanko for e in s. Vendar to ne bo delovalo, ker nam ne zadošča vrednost elementa, temveč potrebujemo tudi njegov indeks. V takih primerih uporabimo enumerate.
def unikati(s):
t = []
for i, e in enumerate(s):
if e not in s[:i]:
t.append(e)
return t
To pa nas pripelje naravnost v rešitev v eni vrstici:
def unikati(s):
return [e for i, e in enumerate(s) if e not in s[:i]]
Očisti
Množica študentov je poskusila
def ocisti(s):
s = unikati(s)
Vendar to ne deluje. Kot smo izvedeli na predavanjih s puščicami, na ta način le priredimo nov seznam (unikati(s)) imenu s znotraj funkcije, ne spreminjamo pa seznama, s katerim smo poklicali funkcijo. Pač pa deluje tole:
def ocisti(s):
s[:] = unikati(s)
Tu vzamemo vse elemente s-ja in jih zamenjamo s tem, kar vrne unikati(s).
Lahko pa se zgledujemo po rešitvi naloge s tviti, ob kateri smo preživeli kar lep kos predavanj, in napišemo:
def ocisti(s):
i = 0
while i < len(s):
if s[i] in s[:i]:
del s[i]
else:
i += 1
Kako in zakaj to deluje, si lahko ogledate v prvi nalogi o tvitih.
Ne spreglejte: ta funkcija ne vrača -- in ne sme vračati -- ničesar.
Podvoji
S trikom od prej: sestavimo nov seznam iz podvojitev elementov podanega, nato pa to porinemo v podani seznam.
def podvoji(s):
t = []
for e in s:
t += [e, e]
s[:] = t
Ali pa z variacijo na mukotrpno brisanje od prej: na i-to mesto vstavimo vrednost i-tega elementa in ga potem preskočimo tako, da i povečamo z 2.
def podvoji(s):
i = 0
while i < len(s):
s.insert(i, s[i])
i += 2
Zdaj pa triki. Podvojimo seznam. Nato na vsa soda in vsa liha mesta vpišemo, kar je bilo prej v prvi polovici seznama.
def podvoji(s):
s *= 2
s[::2] = s[1::2] = s[:len(s) // 2]
Pa še v eni vrstici. In niti ni tako težko. Seznam zamenjamo z elementi, ki jih dobimo tako, da štejemo do dvojne dolžine seznama, v novi seznam pa dodajamo element, ki je na mestu i // 2. Ker celoštevilsko deljenje zaokroža navzdol, bomo tako vedno po dvakrat dobili isti element.
def podvoji1(s):
s[:] = [s[i // 2] for i in range(2 * len(s))]