Testi

Testi: testi-unikati.py

Naloga

  1. Napiši funkcijo unikati(s), ki prejme seznam s in vrne seznam, v kateri so vsi elementi s brez njihovih ponovitev. Vrstni red elementov mora biti enak vrstnemu redu njihovih prvih pojavitev. Klic unikati([5, 4, 1, 4, 4, 4, 4, 4, 3, 1]) vrne [5, 4, 1, 3].

  2. Napiši funkcijo ocisti(s), ki iz seznama s pobriše ponovitve elementov. Če imamo s = [5, 4, 1, 4, 4, 4, 4, 4, 3, 1], naj klic ocisti(s) spremeni s v [5, 4, 1, 3].

  3. Napiši funkcijo podvoji(s), ki spremeni seznam s tako, da se vsak element v njem ponovi dvakrat zapored. Če imamo s = [5, 1, 3, 1, 4], bo po klicu podvoji(s) seznam s 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))]
마지막 수정됨: 수요일, 24 3월 2021, 11:07 PM