22 svar
868 visningar
sandy99 42
Postad: 27 mar 2019 20:17

Python: Modulo, lista, rätt ordning

Hej!

Jag har en lista:

train = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26,
28, 29, 30, 31, 32]

och vill printa ut så att det ser ut något i stil med:

1 5  9  13 17 21 25 29

2 6 10 14 18 22 26 30

 

3 7 11 15 19 23 27 31

4 8 12 16 20 24 28 32

 

Detta ska gå att göra med hjälp av modulo! 

Jag har börjat på något sånt här:

for i in train:
if i % 8 == 0:

 

Jag vill ha 8 på en rad som jag ritat upp ovan :)

 

Tack på förhand!

Laguna Online 30711
Postad: 27 mar 2019 20:53

i%8 == 0 för 8, 16, 24 och 32. Hur passar det in i den utskrift som du vill ha? På den rad där de talen förekommer står det en del andra tal också.

sandy99 42
Postad: 27 mar 2019 20:54

Jaa, såg det när jag försökte printa, jag vill ha 8 tal per rad och 4 rader..

Laguna Online 30711
Postad: 27 mar 2019 20:59

Du får producera en rad i taget och skriva ut den (men det går på andra sätt, t.ex. att först avgöra för alla tal var de ska stå och sedan skriva ut en rad i taget). Det betyder att det är modulo-resten som du ska iterera över i första hand: i%4 == 1, i%4 == 2 osv.

sandy99 42
Postad: 27 mar 2019 21:06

Jag förstår, tack!

Men när jag printar detta:

for i in train:
if i % 4 == 1:
print(i)

får jag

1
5
9
13
17
21
25
29

 

Hur får jag dem på en horisontell rad istället för lodrät?

(det här kanske är jätteenkelt, jag är nybörjare i kod!)

Laguna Online 30711
Postad: 27 mar 2019 21:10
sandy99 skrev:

Jag förstår, tack!

Men när jag printar detta:

for i in train:
if i % 4 == 1:
print(i)

får jag

1
5
9
13
17
21
25
29

 

Hur får jag dem på en horisontell rad istället för lodrät?

(det här kanske är jätteenkelt, jag är nybörjare i kod!)

Enkelt kanske det är, men inte likadant i alla språk, och inte uppenbart. Jag föreslår ett av två sätt: 1) ge ett extra argument till print som säger att den inte ska göra en ny rad, eller 2) samla talen i en lista, och gör sedan en textrad av dem med mellanslag som separator, med " ".join(l) där l är listan.

Eller ha en loop inuti en loop. Modulo-resten i den yttre, som jag sa först, och talen i listan i den inre.

SeriousCephalopod 2696
Postad: 27 mar 2019 21:20 Redigerad: 27 mar 2019 21:22

Alternativ 1 (ful men enkel)

Ha en sträng som du utökar för varje steg i forloopen som man sedan skriver ut efter att forloopen är klar

output_str = ""

for (...):

   output_str = output_str + " " + str(i)

print(output_str)

str.join-kommandon är dock det man vill göra i längden. 

SeriousCephalopod 2696
Postad: 27 mar 2019 21:31 Redigerad: 27 mar 2019 21:32

Nu ska du använda modulo i den här uppgiften men python har sjukt många list-operationer där många av dem specifikt är för att slippa skriva mycket kod för att få sådana här resultat.

train[0:-1:4] ger dig bokstavligen en underlista med var 4:e element. -1 betecknar det sista elementet i listan så läses som; börja vid 0, ta steg om 4 tills dess att du når/passerar -1:e elementet. Ville man ha varannat element men bara mellan index 3 och 9 skulle man skriva train[3:9:2]. Oavsett om du ska hålla på med något annat i den här uppgiften så är det en relevant operation att lära sig. 

sandy99 42
Postad: 28 mar 2019 10:39

Jag har pratat lite med en kompis som tipsade om att göra 4 tomma listor (en per rad) så nu har jag något som ser ut såhär:


rad1 = []
rad2 = []
rad3 = []
rad4 = []

for i in train:
if i % 4 == 1:
print(i)
if i % 4 == 2:
print(i)
if i % 4 == 3:
print(i)
if i % 4 == 4:
print(i)

Jag behöver ha det som en lista då jag behöver kunna accessa alla items i listan via index, så känner att det blir bättre än att ha i en string. Men lite osäker på for loopen :/

Laguna Online 30711
Postad: 28 mar 2019 10:43
sandy99 skrev:

Jag har pratat lite med en kompis som tipsade om att göra 4 tomma listor (en per rad) så nu har jag något som ser ut såhär:


rad1 = []
rad2 = []
rad3 = []
rad4 = []

for i in train:
if i % 4 == 1:
print(i)
if i % 4 == 2:
print(i)
if i % 4 == 3:
print(i)
if i % 4 == 4:
print(i)

Jag behöver ha det som en lista då jag behöver kunna accessa alla items i listan via index, så känner att det blir bättre än att ha i en string. Men lite osäker på for loopen :/

Det här är ungefär mitt förslag 2, men du får stoppa in talet 'i' i lämplig lista i stället för att skriva ut det. Sedan skriver du ut när du har gått igenom hela 'train'.

sandy99 42
Postad: 28 mar 2019 10:48

Tack, ska testa!

sandy99 42
Postad: 28 mar 2019 11:20

Nu är mitt input:

rad1 = []
rad2 = []
rad3 = []
rad4 = []


for i in train:
if i % 4 == 1:
rad1.append(i)
if i % 4 == 2:
rad2.append(i)
if i % 4 == 3:
rad3.append(i)
if i % 4 == 0:
rad4.append(i)


print(rad1)
print(rad2)
print("")
print(rad3)
print(rad4)

 

och mitt output:

[1, 5, 9, 13, 17, 21, 25, 29]
[2, 6, 10, 14, 18, 22, 26, 30]

[3, 7, 11, 15, 19, 23, 27, 31]
[4, 8, 12, 16, 20, 24, 28, 32]

 

Vilket ändå ser ut att vara på rätt spår, men jag vill gärna inte printa ut klamrarna [] eller kommatecknen?

 

Tack för all hjälp!

Laguna Online 30711
Postad: 28 mar 2019 11:24

Då använder du fortsättningen på mitt förslag 2, metoden 'join':

" ".join(rad1) slår ihop rad1 till en textsträng, med mellanslag som separator.

SeriousCephalopod 2696
Postad: 28 mar 2019 11:31

Jag tror man måste ha en listan av strängar (konvertera) för att join ska ungera. Dock inte vid en dator där jag kan kontrollera snabbt. Men ja. Join är det vettigaste här.

sandy99 42
Postad: 28 mar 2019 11:36

Men funkar join och att göra om till string om jag vill kunna accessa indexen i listan,

jag gör ett program för att boka platser på ett tåg och behöver kunna markera platserna i listan med ** (t.ex. om plats 1 bokas kommer det stå *1*) vilket jag ska göra med hjälp av index.

Försökt med join nu men får felet:
Traceback (most recent call last):
print(" ".join(rad1))
TypeError: sequence item 0: expected str instance, int found

Laguna Online 30711
Postad: 28 mar 2019 12:27
SeriousCephalopod skrev:

Jag tror man måste ha en listan av strängar (konvertera) för att join ska ungera. Dock inte vid en dator där jag kan kontrollera snabbt. Men ja. Join är det vettigaste här.

Ja, hoppsan, det måste man ju.

Man kan konvertera listan av heltal till en lista av strängar, med t.ex. en list comprehension.

Men det kanske är bättre att gå igenom varje lista och göra print med extraargumentet som säger att det inte ska göras ny rad.

Laguna Online 30711
Postad: 28 mar 2019 12:29
sandy99 skrev:

Men funkar join och att göra om till string om jag vill kunna accessa indexen i listan,

jag gör ett program för att boka platser på ett tåg och behöver kunna markera platserna i listan med ** (t.ex. om plats 1 bokas kommer det stå *1*) vilket jag ska göra med hjälp av index.

Försökt med join nu men får felet:
Traceback (most recent call last):
print(" ".join(rad1))
TypeError: sequence item 0: expected str instance, int found

Ja, jag hade fel om join, den behöver ha en lista av strängar, inte heltal.

Nu kom du med nya krav på programmet. Hur vet du att en plats är bokad?

SeriousCephalopod 2696
Postad: 28 mar 2019 12:42 Redigerad: 28 mar 2019 12:43

Det här verkar vara samma problem som sandy99 postat trådar om tidigare.

https://www.pluggakuten.se/trad/python-program-for-bokning/

Jag har redan formulerat att sättet jag skulle lösa problemet är med str.format-injektion då även om det är lite småsvårt att få fungera så bidrar det till en Model-View-Controller-separation om man håller utskriftslogiken så långt ifrån rådatan som möjligt. Men du kan gärna utforska andra vägar Laguna om sandy99 gav upp på min väg (vilket jag kan förstå då den är lite svårare).

Laguna Online 30711
Postad: 28 mar 2019 13:22
SeriousCephalopod skrev:

Det här verkar vara samma problem som sandy99 postat trådar om tidigare.

https://www.pluggakuten.se/trad/python-program-for-bokning/

Jag har redan formulerat att sättet jag skulle lösa problemet är med str.format-injektion då även om det är lite småsvårt att få fungera så bidrar det till en Model-View-Controller-separation om man håller utskriftslogiken så långt ifrån rådatan som möjligt. Men du kan gärna utforska andra vägar Laguna om sandy99 gav upp på min väg (vilket jag kan förstå då den är lite svårare).

Ja, allt eftersom problemet växer sig in i hela sitt sammanhang så kan det vara så att en från början bra och enkel lösning slutar vara en bra lösning, så att när det kommer nya krav så måste man designa om hela tiden.

sandy99 42
Postad: 28 mar 2019 16:01

Hej, ja, jag fick inte till det med strängformatering och pratade med en handledare som sade att min tanke om att ha en lista fungerade bra, så jag körde på det. Nu har jag försökt lite olika grejer och det funkar nästan! Ibland har det funkat helt och ibland inte alls men nu har jag input:

rad1 = []
rad2 = []
rad3 = []
rad4 = []


for i in train:
if i % 4 == 1:
rad1.append(i)
if i % 4 == 2:
rad2.append(i)
if i % 4 == 3:
rad3.append(i)
if i % 4 == 0:
rad4.append(i)


def draw_train():
print(rad1)
print(rad2)
print("")
print("Mittgång")
print("")
print(rad3)
print(rad4)
print("")


def get_booking_input(prompt_string):
choice = int(input(prompt_string))
if choice in rad1:
rad1[(choice-1)] = "*" + str(choice) + "*"
elif choice in rad2:
rad2[(choice-1)] = "*" + str(choice) + "*"
elif choice in rad3:
rad3[(choice-1)] = "*" + str(choice) + "*"
elif choice in rad4:
rad4[(choice-1)] = "*" + str(choice) + "*"

return choice


get_booking_input("Vilken plats önskar ni boka?: \n")
draw_train()


def get_cancel_input(prompt_string):
seat = int(input(prompt_string))
if seat in rad1:
rad1[(seat-1)] = seat
elif seat in rad2:
rad2[(seat-1)] = seat
elif seat in rad3:
rad3[(seat-1)] = seat
elif seat in rad4:
rad4[(seat-1)] = seat

return seat


get_cancel_input("Vilken plats önskar ni avboka? \n")
draw_train()

Och om användaren svarar "1" på bägge frågor får jag output:

Vilken plats önskar ni boka?:
1
['*1*', 5, 9, 13, 17, 21, 25, 29]
[2, 6, 10, 14, 18, 22, 26, 30]

Mittgång

[3, 7, 11, 15, 19, 23, 27, 31]
[4, 8, 12, 16, 20, 24, 28, 32]

Vilken plats önskar ni avboka?
1
['*1*', 5, 9, 13, 17, 21, 25, 29]
[2, 6, 10, 14, 18, 22, 26, 30]

Mittgång

[3, 7, 11, 15, 19, 23, 27, 31]
[4, 8, 12, 16, 20, 24, 28, 32]

Alltså, tas inte ** bort när avbokningen sker, den gjorde det förut, sen ändrade jag om lite och nu funkar det inte men det känns som att jag nästan löst problemet!

Laguna Online 30711
Postad: 28 mar 2019 16:09

Ja, "if seat in rad1" är ju inte sann längre när man har bokat, för det står strängen "*1*" där, inte heltalet 1.

Om man ska lagra i själva listan att platsen är bokad får man ta hand om det fallet separat. Kolla om det är en asterisk där och ta ut talet i strängform och konvertera till heltal och sen jämföra.

Som SeriousCephalopod antydde är det bra att hålla isär representationen av informationen och hur informationen skrivs ut. Jag tycker du borde skriva en funktion för att skriva ut listorna, och den får göra det den behöver när den märker att en plats är bokad. Då kan du representera bokat plats på ett mindre kladdigt sätt, t.ex. genom att negera talet (inte helt snyggt, men bättre än med asterisker) eller också lagra bokning helt separat, i t.ex. en 'dict'.

sandy99 42
Postad: 3 apr 2019 23:06

Hej, uppdatering: jag är i princip klar men har ett litet problem: jag har gjort en klass SeatTicket som jag kallar på senare i funktionen execute() men när jag kör programmet får jag ett TypeError att create_ticketfile från SeatTicket när jag kallar på den i execute saknar ett argument place? Har testat att ändra en massa grejer men det är alltid något som inte stämmer :/

Tack på förhand!


def get_input(prompt_string):
"""
Used to get an inPUT from the user, asks again if input is
not convertible to int
:param prompt_string: the string explaining what to input
:return: the int that was asked for
"""
option = input(prompt_string)
return option


def get_int_input(prompt_string):
"""
Used to get an integer from the user (the user's choice), asks again if input is
not convertible to int
:param prompt_string: the string explaining what to input
:return: user's choice (an integer)
"""
while True:
try:
choice = int(input(prompt_string))
except ValueError:
print("Du måste ange ett heltal.")
else:
return choice


class SeatTicket:
"""
Attributes:
place: place on train
"""

def __init__(self, place):
self.place = place

def __str__(self):
return "{}".format(self.place)

def create_ticket_file(self, place):
self.place = place

f = open("ticketfile.txt", "w+")
f.write("PLATSBILJETT\n"
"Stockholm - Göteborg\n"
"Plats " + str(place) + "\n")
f.close()
f = open("ticketfile.txt", "r")
if f.mode == "r":
contents = f.read()

print(contents)


all_seats = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26,
28, 29, 30, 31, 32]

booked_list = []

available_seats = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26,
28, 29, 30, 31, 32]

rad1 = []
rad2 = []
rad3 = []
rad4 = []


for i in all_seats:
if 1 <= i <= 8:
rad1.append(i)
elif 9 <= i <= 16:
rad2.append(i)
elif 17 <= i <= 24:
rad3.append(i)
elif 25 <= i <= 33:
rad4.append(i)


def draw_train():
"""
Used to print train with updated seat information
:return: nothing
"""
print(rad1)
print(rad2)
print("")
print("Mittgång")
print("")
print(rad3)
print(rad4)
print("")


def unbooked_train():
"""
Used to welcome user to the booking system and to draw the train with no booked seats
:return: nothing
"""
print("\n---------------------------------------\n"
"\n SJ BOKNINGSPORTAL\n"
"Välkommen till SJ:s bokningsportal!\n"
"Välj vad ni önskar göra i menyn nedan.\n"
"Tack för att ni reser med SJ.\n"
"\n"
"\n---------------------------------------\n"
"-----------------------\n"
"1 2 3 4 5 6 7 8 \n"
"9 10 11 12 13 14 15 16\n"
"-----------------------\n"
"\n"
"Mittgång\n"
"\n"
"-----------------------\n"
"17 18 19 20 21 22 23 24\n"
"25 26 27 28 29 30 31 32\n"
"-----------------------\n")


def booking_input():
"""
Used to book tickets on train, calls on function get_int_input (earlier defined) for the user to add an input
:return: the user's choice or, in case the seat has already been booked, a string communicating this to the user
"""
number_of_seats = get_int_input("Hur många platser önskar ni boka? ")
for i in range(number_of_seats):
seatnumber = get_int_input("Vilken plats vill ni boka? ")
if seatnumber in available_seats:
booked_list.append(seatnumber)
available_seats.remove(seatnumber)
if seatnumber in rad1:
rad1[int(seatnumber)-1] = " "
elif seatnumber in rad2:
rad2[(int(seatnumber) - 9)] = " "
elif seatnumber in rad3:
rad3[(int(seatnumber) - 17)] = " "
elif seatnumber in rad4:
rad4[(int(seatnumber) - 25)] = " "
else:
print("Denna plats har redan blivit bokat, vänligen välj en annan. ")

return seatnumber


def cancel_input(prompt_string):
"""
Used to cancel tickets on the train
:param prompt_string: Used to get input from users on what teat they wish to cancel
:return: seat
"""
while True:
seat = int(input(prompt_string))
try:
if seat not in available_seats:
booked_list.remove(seat)
available_seats.append(seat)
if seat in all_seats:
print("1"+rad1[seat - 1])
rad1[seat-1] = seat
elif seat in all_seats:
print("2"+rad2[seat - 1])
rad2[(seat - 9)] = seat
elif seat in all_seats:
print("3"+rad3[seat - 1])
rad3[(seat - 17)] = seat
elif seat in all_seats:
print("4"+rad4[seat - 1])
rad4[(seat - 25)] = seat
except ValueError:
print("Denna plats finns inte på tågvagnen och går därför inte att avboka.")

return seat


def menu():
"""
Used to print out the menu for the user to see
:return: nothing
"""
print("Vad vill du göra?\n"
"'B' - Boka tågbiljett\n"
"'A' - Avboka tågbiljett\n"
"'S' - Skriva ut senast bokad biljett\n"
"'Q' - Avsluta programmet\n"
"\n")


def menu_choice():
"""
Used to get the user's menu option
:return: the user's menu option
"""
return get_input("Ditt val: ")


def execute(option):
"""
Used to execute the user's choice, either book a ticket, cancel a ticket, print a ticket or exit the program
:param option: The user's menu option
:return: nothing
"""
if option == "B":
print("Avgångar:\n"
"1 - Stockholm\n")
get_int_input("Välj avgång: \n")
print("Destinationer:\n"
"1 - Göteborg\n")
get_int_input("Välj destination: \n")
booking_input()
draw_train()

elif option == "A":
cancel_input("Vilken plats önskar ni avboka? \n")
draw_train()

elif option == "S":
place = get_int_input("För vilken plats vill ni skriva ut en biljett? ")
if place in booked_list:
SeatTicket.create_ticket_file(place)
else:
print("Denna plats har inte blivit bokad. För att boka en biljett, välj 'B' i menyn.\n")

elif option == "Q":
print("Tack för att ni använder SJ.\n")
print("Avslutar...\n")
quit()

elif option != "B" or "A" or "S" or "Q":
print("Det här alternativet är inte tillgängligt. Svara med stora bokstäver.\n")


def main():
"""
Used to run the program and to discontinue if the user chooses to exit the program
:return: nothing
"""
choice = ""
while choice != "Q":
menu()
execute(menu_choice())


unbooked_train()
main()

Laguna Online 30711
Postad: 4 apr 2019 07:00

Såvitt jag kan se är create_ticketfile skriven för att anropas som metod för en instans (self är första argument), men du anropar den utan någon instans, med klassens namn i stället.

Svara
Close