Matrizen erstellen mittels List Comprehensions

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
mbh
User
Beiträge: 10
Registriert: Montag 9. Mai 2016, 19:35

Guten Abend zusammen,

ich bin neu im Forum und hoffe, ich hab mich an alle Regeln gehalten.
Wir haben seit diesem Semester Python an der Uni und müssen jede Woche ein paar Aufgaben lösen.
Bis jetzt bin ich gut mitgekommen, aber heute stehe ich etwas an. :(
Wir sollen mittels List Comprehensions ohne klassische for Schleifen Matrizen (als Listen in Listen) erzeugen, zB diese:
(1 2 3 4 5)
(2 3 4 5 1)
(3 4 5 1 2)
(4 5 1 2 3)
(5 1 2 3 4)
Die Bsp in denen wir mittels LC einzelne Listen erzeugen sollten, hab ich hinbekommen, aber bei Listen in Listen bin ich grad ziemlich überfordert. Mit

Code: Alles auswählen

[[x,y] for x in liste1 for y in liste2]
lässt sich eine Liste aus Listen die aus allen Kombinationen der Elemente aus Liste 1 und Liste 2 bestehen. Aber dabei wird doch jedes Element mit jedem kombiniert und außerdem wäre das bei 5 Elementen je Zeile auch extrem mühsam zu schreiben. Ich hab das Gefühl, dass ich irgendwo komplett auf der Leitung stehe, kann mir jemand vielleicht auf die Sprünge helfen?
Danke! :)
LG Mana
BlackJack

@mbh: Wie so oft muss man das Problem auf kleinere Teilprobleme runterbrechen. Schreib eine LC die eine Unterliste erstellt, überlege wie man die ändern müsste damit man einen Wert von aussen setzen kann so das in Abhängigkeit von diesem Wert auch die anderen erstellt werden können, und dann verwendest Du diese LC für die Berechnung eines Wertes in einer anderen LC welche die Werte liefert die die erste, jetzt innere LC mit dem Wert von aussen versorgt. Schreib am besten für die Zeilen erst einmal eine Funktion die eine LC benutzt. Vielleicht fällt es dann einfacher. Wenn das läuft kannst Du die LC aus der Funktion direkt einsetzen.
mbh
User
Beiträge: 10
Registriert: Montag 9. Mai 2016, 19:35

Hallo BlackJack,
danke für die schnelle Antwort.
Ich bin nicht sicher, ob ich etwas Sinnvolles damit anfangen konnte:
Ich hätte für die einzelnen Zeilen Folgendes hingemurkst:

Code: Alles auswählen

zeile = [x + i if (x + i < 6) else x + i - 5 for x in range(5)]
Je nachdem welchen Wert i zwischen 1 und 5 annimmt, beginnt die Liste mit i und zählt bis 5, danach wieder von 1.
Weiß nicht, ob du das mit "von außen" gemeint hast, oder ob ich komplett am Schlauch stehe..
Wenn ich es dann in eine weitere LC packe, wird es noch schlimmer ^^
Mit

Code: Alles auswählen

matrix = [zeile for i in range(1,6)]
passiert gar nix, wohl weil er i nur durchiteriert und nicht als Variable für mein "zeile" nutzt?? Ich glaub, da hab ich irgendwas komplett falsch verstanden :/
mbh
User
Beiträge: 10
Registriert: Montag 9. Mai 2016, 19:35

Ahh! Mit

Code: Alles auswählen

matrix = [[x + i if (x + i < 6) else x + i - 5 for x in range(5)] for i in range(1,6)]
haut's hin.. Danke!!
Wär super, wenn du mir vl noch sagen könntest, ob meine Lösung so sehr umständlich oder halbwegs vernünftig ist. :)
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@mbh: das sieht doch schon ganz gut aus, obwohl man da schnell merkt, dass verschachtelte List-Comprehensions schwer zu lesen sind und es besser wäre zumindest die innere Schleife in eine Funktion auszulagern:

Code: Alles auswählen

def generate_row(i):
    return [x + i if x + i < 6 else x + i - 5 for x in range(5)]

matrix = [generate_row(i) for i in range(1,6)]
Die Klammern um die if-Bedingung sind übrigens überflüssig. Einfacher geht es noch mit dem Modulo-Operator.
sebastian0202
User
Beiträge: 168
Registriert: Montag 9. Mai 2016, 09:14
Wohnort: Berlin

Ich habe mich auch an der Aufgabe versucht. Aber so schön kurz wie diese List Comprehension ist es nicht. :lol:

Code: Alles auswählen

def matrizen_generierung(matrizen_groesse=5):
    for nummer in range(1, matrizen_groesse + 1):
        matrize = []
        for zahl in range(nummer, nummer + matrizen_groesse):
            if zahl > matrizen_groesse:
                matrize.append(zahl - matrizen_groesse)
            else:
                matrize.append(zahl)
        yield matrize


def main():
    matrizen = [matrize for matrize in matrizen_generierung()]
    for matrize in matrizen:
        print matrize

if __name__ == '__main__':
    main()

mbh
User
Beiträge: 10
Registriert: Montag 9. Mai 2016, 19:35

@Sirius3: alles klar, danke!

@sebastian0202: intuitiv hätte ich es auch lieber mit Listen gelöst :)
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@sebastian0202: Du benutzt eigentlich gar keine List-Comprehension, denn die einzige LC ließe sich schöner schreiben:

Code: Alles auswählen

matrizen = list(matrizen_generierung())
PS: was ist die Singularform von Matrizen?
sebastian0202
User
Beiträge: 168
Registriert: Montag 9. Mai 2016, 09:14
Wohnort: Berlin

Stimmt, die Aufgabe sollte mit LC gelöst werden. Die einzige LC von mir war aber auch unnötig.
Wie eine verschachtelte LC aussieht konnte ich mir nicht vorstellen.

Oh, anstelle Matrize lieber Matrix.
Habe irgendwie an Matratze gedacht. :P
BlackJack

@mbh: Was das umständlich angeht: Die Berechnung eines einzelnen Wertes würde ich wohl anders lösen. Ohne Fallunterscheidung. Vielleicht fällt Dir an der Stelle ja eine Verwendung für den Modulo-Operator ein. :-)
mbh
User
Beiträge: 10
Registriert: Montag 9. Mai 2016, 19:35

@BlackJack:

Code: Alles auswählen

[(x+i-1)%5+1 for x in range(5)]
Sieht viel besser aus, danke :D
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Code: Alles auswählen

def make_matrix(n):
    return [[((i + j) % n) + 1 for i in range(n)] for j in range(n)]

print(make_matrix(5))
Alternativ:

Code: Alles auswählen

def make_row(start, limit):
    return [((start + n) % limit) + 1 for n in range(limit)]

def make_matrix(limit):
    return [make_row(start, limit) for start in range(limit)]

print(make_matrix(5))
Antworten