2009-08-26, 13:14
  #1
Medlem
Jag är nybörjare på python och skulle behöva hjälp med att komma vidare med mitt pythonprogram som ska kunna sortera bilar efter månadskostnad.
Bilarna läses in från en textfil som ser ut som följer:

% Format: märke /modell/ pris / försäkringspremie
ford
focus
200000
5000
osv.

Användaren börjar med att ange kontantinsats och ränta:

kontantinsats = int(raw_input("Ange kontantinsats (kr):"))

ränta = float(raw_input("Ange låneränta (procent):"))

Jag har gjort en variant som bara använder första objektet i textfilen, dvs "ford focus".:

bil = open("bilar.txt", "r")
bilar = bil.readlines()
bil.close()

bilpris = int(bilar[3])
försäkring = int(bilar[4])


total_månadskostnad = försäkring/12+(1.0/12.0)*(bilpris-kontantinsats)*(ränta/100.0)
print "Månadskostnad (kapitalkostnad+försäkring):"
print total_månadskostnad

Men jag vill nu ordna så att jag kan räkna ut månadskostnaden för samtliga objekt i textfilen samt sortera dessa map månadskostnad. Är det en vettig idé att skapa en separat lista för varje objekt i textfilen? Tacksam för uppslag för hur jag kan komma vidare.
Citera
2009-08-26, 13:45
  #2
Medlem
DOGKAiSERs avatar
Använd dictionary.

Om du har en fil enligt följande mönster (förtstod inte om du hade newline mellan varje info, det är onödigt):
ford|focus|20000|5000
saab|95|22000|6000


Kod:
#läs kontantinsats/ränta
kontantinsatsranta raw_input("kontantinstats låneränta").split(' ')

#läs in data:
f=open("bilar.txt","r")
data=f.read().split("\n")

#gör en ny dictionary
bilar={}
#gå igenom rader
for r in range(len(data)):
  
bil=data[r].split("|")
  
bilar[int(bil[3])/12+(1.0/12.0)*(int(bil[2])-int(kontantinsats))*(float(ranta)/100.0)]=bil[0]+" "+bil[1]

#skriv ut
for e in bilar: print str(e)+"\t"+bilar[e
__________________
Senast redigerad av DOGKAiSER 2009-08-26 kl. 13:48.
Citera
2009-08-26, 15:45
  #3
Medlem
Är dictionary verkligen mest lämpligt i ett fall som detta? Textfilen ser ut som den gör och eftersom den innehåller så många bilar är det ett stort jobb att ta bort newline mellan varje info.

Har istället prövat att försöka skapa en ny lista där månadskostnaden läggs till som en ny rad för varje bil. Tanken är att man sen ska kunna sortera bilarna efter månadskostnaden. Får inte koden att funka dock. Någon som har förslag på hur man kodar för att lägga in formeln:
total_månadskostnad = försäkring/12+(1.0/12.0)*(bilpris-kontantinsats)*(ränta/100.0)
som ett nytt element i listan efter varje bil?
Citera
2009-08-26, 17:03
  #4
Medlem
DOGKAiSERs avatar
Dictionary är helt klart bäst.
1. Sorteras automatiskt från billigast till dyrast om du använder kostnaden som key.
2. Du kan sortera från max->min eller inom olika prisnivåer utan att behöva krångla till det.

Så din bilar.txt följer detta mönster:
% Format: märke /modell/ pris / försäkringspremie
ford
focus
200000
5000
% Format: märke /modell/ pris / försäkringspremie
saab
95
25000
6000

Kod:
#ta input
kontantinsatsranta raw_input("kontantinstats låneränta\n").split(' '

#läs data
f=open("bilar.txt","r")
data=f.read().split("\n")

#generera output
bilar={}
for 
r in range(1,len(data),5):
  
bilar[(((int(data[r+3])/12)+(1.0/12.0))*(int(data[r+2]))-int(kontantinsats))*(float(ranta)/100)]=(data[r]+" "+data[r+1])

#skriv ut
print "Månadskostnad\tBil"
for e in bilar: print str(e)+"\t"+bilar[e


Om du nu vill visa dyrast till billigast:

Kod:
price_list=bilar.keys()#alla nycklar (dvs. kostnader) i bilar dict
price_list.sort(reverse=True)#vi reversar
for val in price_list: print str(val)+"\t"+bilar[val]#skriver ut 

Om du enkom använder dig av en vanlig lista, tex:
l=["Ford",129812,"Mercedes",12829]
blir det mycket jobbigare att sortera efter värde och sedan skriva ut rätt bil.
__________________
Senast redigerad av DOGKAiSER 2009-08-26 kl. 17:06.
Citera
2009-08-26, 17:15
  #5
Medlem
DOGKAiSERs avatar
Kom på att iom att du har så många bilar i din lista kan det ev. bli så att två bilar har samma kostnad.

Detta löser man genom att ändra:
Kod:
#generera output
bilar={}
for 
r in range(1,len(data),5):
  
bilar[(((int(data[r+3])/12)+(1.0/12.0))*(int(data[r+2]))-int(kontantinsats))*(float(ranta)/100)]=(data[r]+" "+data[r+1]) 

till:
Kod:
#generera output
bilar={}
for 
r in range(1,len(data),5):
  
varde=(((int(data[r+3])/12)+(1.0/12.0))*(int(data[r+2]))-int(kontantinsats))*(float(ranta)/100)
  if 
bilar.has_key(varde): bilar[varde]+=", "+data[r]+" "+data[r+1]
  else: 
bilar[varde]=data[r]+" "+data[r+1
Citera
2009-08-26, 19:13
  #6
Medlem
Tack så jättemycket för hjälpen DOGKAiSER!
Citera
2009-08-27, 01:13
  #7
Medlem
Jag hade gjort en klassisk decorate-sort-undecorate. I detta fall skapat en ny lista där varje element är en tuple på formen (månadskostnad, bilobjekt). Sedan hade jag kört sort() på listan och plockat ut bilobjekten i den sorterade ordningen. sort() sorterar efter första värdet i tuplen först, sedan andra, osv. bilobjekt kan här vara den info du parseade från din textfil i nån lämpligt form.
Citera
2009-08-27, 14:19
  #8
Medlem
hur hade en sådan kodning kunnat se ut?
Citera
2009-08-27, 14:39
  #9
Medlem
Om vi bara låtsas att vi redan har läst och parseat bilar.txt till en lista av dictar med nycklarna märke, modell, pris, försäkringspremie, alltså
Kod:
bilar = [
    {
'märke''ford''modell''focus''pris'200000'försäkringspremie'5000}, 
    {
'märke''saab''modell''95''pris'25000'försäkringspremie'6000}, 
    ...
osv...

så skulle man kunna göra nåt i stil med följande:
Kod:
kontantinsatsränta raw_input("kontantinsats låneränta\n").split(' '

sortlist = []

for 
bil in bilar:
    
total_månadskostnad bla bla
    sortlist
.append((total_månadskostnadbil))

sortlist.sort()

for 
tb in sortlist:
    print 
"%s %s: %.0f" % (b['märke'], b['modell'], t
Citera
2009-09-03, 11:27
  #10
Medlem
Känner mig väldig osäker på hur nedanstående kod fungerar. Kan någon vänlig själ kommentera mer ingående hur forslingan fungerar? Kommentera gärna så detaljerat som möjligt!

#generera output
bilar={}
for r in range(1,len(data),5):
bilar[(((int(data[r+3])/12)+(1.0/12.0))*(int(data[r+2]))-int(kontantinsats))*(float(ranta)/100)]=(data[r]+" "+data[r+1])

#skriv ut
print "Månadskostnad\tBil"
for e in bilar: print str(e)+"\t"+bilar[e]
Citera
2009-09-06, 05:03
  #11
Medlem
Aardwarks avatar
Skapa en klass (eller håll koll på en tuple själv) för informationen. Sen lägg det i en lista (eller dictionary om du tycker det är logiskt.. vad skulle du ha som key? tuplen (bilmärke, modell) isåfall).

Det är en hel del konstiga lösningar i denna tråden. T.ex. blir en dictionary inte enklare än en lista, snarare blir det bara bökigare (och långsammare). För att få den att sortera på just månadskostnad (precis varje gång) kan man skapa lägga objekt på listan såhär:

<code>List.append( (monthly_cost, price, brand, model) )</code>

så sorteras den korrekt (eftersom den kommer sortera på första elementet först) vid ett anrop till List.sort() .

men annars är det nog mer logiskt med t.ex. ((brand, model), price, monthly_cost) och ska du sen sortera en lista på price, så skriver man
<code>List.sort( key=lambda x:x[1] )</code>. Har du inte sett lambda förut så får du kolla upp det, men det är helt enkelt en "on the fly"-skapad funktion. Det hade gått lika bra med
<code>def byPrice(x):
return x[1] # x[1] for ((M,m), price, monthly) -> price

L.sort(key=byPrice)</code> då key ska vara en funktion som returnerar det värdet som listan ska sorteras efter.
Citera
2009-09-10, 18:28
  #12
Medlem
På nytt:

En textfil med följande innehåll:

%Format:märke/modell/pris/försäkringspremie
ford
focus
200000
5000
saab
95
220000
6000
mercedes
vito
600000
12000


Följande kod har knåpats ihop:
##-*-coding:Latin-1 -*-
ränta = float(raw_input("Vänligen ange aktuell bankränta (procent):"))

kontantinsats = int(raw_input("Vänligen ange kontantinsats (kr):"))

#Läser in bilar2.txt
f=open("bilar2.txt","r")
data1=f.read().split("\n")
f.close()


#Tar bort första raden i "data1" då den är ointressant
data=data1[1:]

#Skriver rubrik till listan som presenteras genom for-slingan

print "Märke:\t\t\tModell:\t\t\tTotal månadskostnad:"
print "\n"



for r in range(0,len(data)-1,4):

märken=(data[r])

modeller=(data[r+1])

priser=int(data[r+2])

försäkringar=float(data[r+3])

#Räknar ut månadskostnaderna för varje bil
månadskostnader = försäkringar/12.0+(priser-kontantinsats)*(ränta/100.0)

print str(märken)+"\t\t\t"+str(modeller)+"\t\t\t"+str(må nadskostnader)

Nu skrivs bilarna och dess totala månadskostnad ut. Nu vill jag sortera så att bilarna sorteras map månadskostnad så att billigaste bilen skrivs först, näst billigast på raden under osv. Några förslag?
Citera

Skapa ett konto eller logga in för att kommentera

Du måste vara medlem för att kunna kommentera

Skapa ett konto

Det är enkelt att registrera ett nytt konto

Bli medlem

Logga in

Har du redan ett konto? Logga in här

Logga in