Unikati
Testi
Testi: testi-unikati.py
Naloga
Napiši funkcijo
unikati(s)
, ki prejme seznams
in vrne seznam, v kateri so vsi elementis
brez 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 seznamas
pobriše ponovitve elementov. Če imamos = [5, 4, 1, 4, 4, 4, 4, 4, 3, 1]
, naj klicocisti(s)
spremenis
v[5, 4, 1, 3]
.Napiši funkcijo
podvoji(s)
, ki spremeni seznams
tako, da se vsak element v njem ponovi dvakrat zapored. Če imamos = [5, 1, 3, 1, 4]
, bo po klicupodvoji(s)
seznams
enak[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))]