Napišite funkcijo knjigovodstvo(ime_datoteke)
, ki prejme
ime datoteke s prihodki (vrstice s pozitivnimi števili) in odhodki
(negativna števila) v obliki, kot jo kaže okvirček na desni. Funkcija
mora vrniti trojko: seznam s pari imen dohodkov in pripadajočih zneskov,
seznam s pari imen odhodkov in pripadajočih cen (kot pozitivna števila)
ter skupno vsoto. Za datoteko
slika: 50
slika: 100
tempera: -3
stol: -20
kip: 20
zrak: 0
torba: 12
vrne
([('slika', 50), ('slika', 100), ('kip', 20), ('torba', 12)],
[('tempera', 3), ('stol', 20)],
159)
pri čemer je 159 preprosto vsota vseh številk.
Najprej pripravimo, kar bomo vrnili - seznama prihodki
in odhodki
ter bilanca
.
Nato gremo po datoteki: vsako vrstico razdelimo glede na
:
in pretvorimo znesek v število. Če je šteivlo negativno,
dodamo par s stvarjo in zneskom v odhodki
(pri čemer mora
biti število -znesek
), sicer v prihodki
. Pa
bilanco
povečamo za znesek
.
def knjigovodstvo(ime_datoteke):
= []
prihodki = []
odhodki = 0
bilanca for vrstica in open(ime_datoteke):
= vrstica.split(":")
stvar, znesek = int(znesek)
znesek if znesek < 0:
-znesek))
odhodki.append((stvar, elif znesek > 0:
prihodki.append((stvar, znesek))+= znesek
bilanca return prihodki, odhodki, bilanca
Nekateri radi pišejo
if znesek > 0:
bilanca += znesek
else:
bilanca -= abs(znesek)
To seveda ni potrebno. Python zna prištevati negativne vrednosti. :)
Prav tako je lepo, da bilanco spreminjamo izven if
in ne
znotraj, ločeno za odhodke in za prihodke.
Eden od študentov je poskusil nalogo rešiti z numpy
-jem.
Sicer se mu ni čisto posrečilo, vendar gre in je kar lepo. Dobra
ideja.
def knjigovodstvo(ime_datoteke):
= np.genfromtxt(ime_datoteke, delimiter=":", dtype=str)
podatki = podatki[:, 0]
stvari = podatki[:, 1].astype(int)
cene = cene > 0
prihodki = cene < 0
odhodki return (list(zip(stvari[prihodki], cene[prihodki])),
list(zip(stvari[odhodki], -cene[odhodki])),
sum(cene)) np.
Zoprna stvar je tisto na koncu: z zip
poberemo skupaj
stvari in cene, da nam sestavi pare, potem pa pokličemo še
list
, da jih zložimo v seznam.
Napiši funkcijo draginja(odhodki)
, ki vrne seznam parov
imen stvari in cen. Ista stvar se lahko pojavi večkrat, a morda z
različnimi cenami. Funkcija mora vrniti ime stvari, katere povprečna
cena je bila največja. Če je takšnih stvari več, lahko vrne poljubno
izmed njih.
Klic
draginja([('stol', 20), ('torba', 12), ('tempera', 3), ('miza', 50), ('stol', 30), ('stol', 60), ('miza', 40), ('torba', 5)])
vrne 'miza'
, saj je povprečna cena miz enaka
(50 + 40) / 2 = 45
, medtem ko je povprečna cena, recimo,
stolov (20 + 30 + 60) / 3 = 36,66
, torbe in tempere pa so
še cenejše.
Tole je naloga iz slovarjev. Da bomo lahko računali povprečne cene, bomo potrebovali dva: v enem beležimo vsote cen vsake stvari, v drugem število takšnih stvari.
Ko se odločimo glede tega, je funkcija preprosta.
def draginja(odhodki):
= defaultdict(float)
skupna_cena = defaultdict(int)
skupno_kosov for stvar, cena in odhodki:
+= cena
skupna_cena[stvar] += 1
skupno_kosov[stvar]
= None, -1
naj_stvar, naj_povp for stvar in skupna_cena:
= skupna_cena[stvar] / skupno_kosov[stvar]
povp if povp > naj_povp:
= stvar, povp
naj_stvar, naj_povp return naj_stvar
Zoprni drugi del se da skrajšati, če znamo bolj spretno uporabljati
max
in poznamo lambde
.
def draginja(odhodki):
= defaultdict(float)
skupna_cena = defaultdict(int)
skupno_kosov for stvar, cena in odhodki:
+= cena
skupna_cena[stvar] += 1
skupno_kosov[stvar] return max(skupna_cena, key=lambda stvar: skupna_cena[stvar] / skupno_kosov[stvar])
Napišite funkcijo dragocenosti(stvari, cene, meja)
, ki
prejme numpy-jevo tabelo z imeni stvari in dvodimenzionalno tabelo,
katere vrstice ustrezajo stvarem (v enakem vrstnem redu kot so te
naštete v prvi tabeli), stolpci pa dnevom. Vrednosti v tabeli povedo,
koliko je stvar stala na posamezni dan.
Funkcija mora vrniti tabelo z imeni vseh stvari, katerih cene so bile vsaj en dan višje od podane meje meja. Vrstni red mora biti enak vrstnemu redu v tabeli stvari.
Pri tej nalogi pričakujemo rešitev v čistem numpy-ju, brez zank v Pythonu.
Takole.
def dragocenosti(stvari, cene_po_dnevih, meja):
return stvari[np.any(cene_po_dnevih > meja, axis=1)]
Ali pa takole.
def dragocenosti(stvari, cene_po_dnevih, meja):
return stvari[np.max(cene_po_dnevih, axis=1) > meja]
Ko poženete teste, se bo v direktoriju s programom pojavila datoteka knjigovodstvo.html. Lahko jo odprete v brskalniku ali urejevalniku.
Napišite funkcijo spletno_knjigovodstvo(ime_datoteke)
,
ki zna prebrati podatke iz takšne datoteke. Predpostaviti smete, da opis
nakupa vedno vsebuje le eno število ter da je to število pozitivno in
celo. Funkcija mora vrniti seznam s pari stvari in cen. Za podano
datoteko naj vrne
[('slika', 50), ('slika', 100), ('tempera', 3), ('polomljen stol', 20), ('kip', 20), ('zrak', 0), ('torba', 12)]
.
Seveda bomo uporabili BeautifulSoup
in regularne
izraze.
Podatki so v delu HTML-ja, ki je videti tako:
<dt>slika</dt>
<dd>Stala je 50, lahko bi tudi malo manj.</dd>
<dt>slika</dt>
<dd>Ta je bila malo dražje, zanjo smo dali 100.</dd>
Poiščemo vse dt
in potem dd
, ki jim
sledijo. Znotraj tega, kar je bilo v dd
poiščemo zaporedja
števk \d+
. Kar najdemo, pretvorimo v število.
def spletno_knjigovodstvo(ime_datoteke):
= BeautifulSoup(open(ime_datoteke), "html.parser")
soup = []
postavke for vrstica in soup.find_all("dt"):
= vrstica.text
stvar = vrstica.find_next_sibling("dd").text
opis = re.search(r"\d+", opis).group()
znesek int(znesek)))
postavke.append((stvar, return postavke
Napišite funkcijo evidenca(postavke, ime_datoteke)
, ki
prejme postavke v obliki trojk z imenom stvarmi, ceno za kos in številom
kosov, na primer
[("slika", 50, 2), ("tempera", 3, 1), ("stol", 20, 1), ("kip", 20, 12), ("zrak", 0, 141), ("torba", 12, 1)]
.
Funkcija mora v datoteko ime_datoteke zapisati tabelo v obliki, ki jo
kaže slika na desni. Točno obliko - število presledkov - razberite iz
testov.
Stvar Cena x Kosov Skupaj
------------------------------------
slika 50 x 2 100
tempera 3 x 1 3
stol 20 x 1 20
kip 20 x 12 240
zrak 0 x 141 0
torba 12 x 1 12
Tule gre zgolj za osnovno oblikovanje nizo: prešteti moramo, na
koliko znakov poravnamo kakšno stvar, pa z >
in
<
potiskati stvari na desno in na levo.
def evidenca(postavke, ime_datoteke):
= open(ime_datoteke, "w")
f f"{'Stvar':10} {'Cena':>6} x {'Kosov':<5} {'Skupaj':>10}\n")
f.write("-" * 36 + "\n")
f.write(for stvar, cena, kosov in postavke:
f"{stvar:10} {cena:>6} x {kosov:<5} {cena * kosov:10}\n") f.write(