Seite 1 von 1

Frage zu for-schleifen und Listen

Verfasst: Donnerstag 29. August 2013, 16:03
von Malinka
Ich bin noch nicht so fit in Python und hoffe, dass ihr mir bei folgendem Problem helfen könnt:

Ich möchte mithilfe einer for-Schleife verschiedene Listen erzeugen. Mit jedem Durchlauf erzeuge ich also eine Liste. Wie kann ich nun anschließend auf einzelne erzeugte Listen zugreifen, um die Listen aus allen Durchläufen miteinander zu vergleichen?

Ich hoffe, meine Frage ist verständlich, wenn nicht, bitte ich euch, mir zu sagen, was unverständlich ist :wink:

Re: Frage zu for-schleifen und Listen

Verfasst: Donnerstag 29. August 2013, 16:09
von BlackJack
@Malinka: Du könntest die Listen zum Beispiel in einer Liste speichern.

Re: Frage zu for-schleifen und Listen

Verfasst: Donnerstag 29. August 2013, 16:16
von Malinka
Und wie mache ich das?
Ich hatte dazu jetzt die Idee, außerhalb der for-Schleife eine neue Liste anzulegen, die den Inhalt der for-Schleife enthält, aber irgendwie scheint das wohl falsch zu sein.

Re: Frage zu for-schleifen und Listen

Verfasst: Donnerstag 29. August 2013, 16:23
von /me
Malinka hat geschrieben:Ich hatte dazu jetzt die Idee, außerhalb der for-Schleife eine neue Liste anzulegen, die den Inhalt der for-Schleife enthält, aber irgendwie scheint das wohl falsch zu sein.
Wahrscheinlich hast du es nur falsch umgesetzt.

Code: Alles auswählen

>>> import random
>>> datapool = []
>>> for _ in range(3):
	data = [random.randint(1, 10), random.randint(1, 5), random.randint(1, 3)]
	datapool.append(data)

>>> print datapool
[[6, 5, 3], [4, 5, 2], [8, 5, 3]]
>>> for entry in datapool:
	print entry

[6, 5, 3]
[4, 5, 2]
[8, 5, 3]
datapool ist die Liste, die die anderen Listen aufnimmt. Innerhalb der Schleife wird jeweils eine neue Liste mit Namen data erstellt und der Liste datapool als Element zugefügt.

Die Ausgabe nach der Schleife zeigt das Ergebnis.

Re: Frage zu for-schleifen und Listen

Verfasst: Donnerstag 29. August 2013, 16:24
von BlackJack
@Malinka: Du legst eine leere Liste an, und jede erzeugte Liste in der ``for``-Schleife hängst Du an diese Liste an.

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf8
from pprint import pprint
from random import randint


def main():
    result = list()
    for _ in xrange(10):
        result.append([randint(1, 6) for _ in xrange(5)])
    pprint(result)


if __name__ == '__main__':
    main()
Ergebnis:

Code: Alles auswählen

[[6, 2, 2, 6, 1],
 [6, 4, 2, 6, 6],
 [2, 1, 3, 6, 5],
 [1, 4, 1, 5, 4],
 [2, 2, 4, 2, 2],
 [2, 6, 3, 5, 5],
 [4, 3, 1, 1, 2],
 [5, 1, 5, 5, 3],
 [5, 1, 3, 3, 6],
 [2, 1, 5, 4, 4]]
Wobei man die äussere ``for``-Schleife hier wahrscheinlich auch durch eine „list comprehension” ersetzen könnte, ohne dass es zu unverständlich wird.

Re: Frage zu for-schleifen und Listen

Verfasst: Donnerstag 29. August 2013, 16:37
von Malinka
Ohjeee, ich glaube, ich muss mir noch einiges an Grundlagen anschauen. :? :shock:

Gibt es vielleicht auch eine Version ohne Module zu importieren? :wink:

Auf jeden Fall danke schonmal.

Re: Frage zu for-schleifen und Listen

Verfasst: Donnerstag 29. August 2013, 16:44
von Malinka
So, ich habe jetzt einfach nur folgendes gemacht:

1. Neue Liste angelegt:
liste1 = []

2. Ans Ende der for-Schleife:
liste1.append(liste)

Das sollte doch reichen, oder? Sieht auf jeden Fall ganz gut aus :wink:

Re: Frage zu for-schleifen und Listen

Verfasst: Donnerstag 29. August 2013, 16:49
von /me
Malinka hat geschrieben:Ohjeee, ich glaube, ich muss mir noch einiges an Grundlagen anschauen. :? :shock:

Gibt es vielleicht auch eine Version ohne Module zu importieren? :wink:
random bzw. pprint waren ja nur zum Erzeugen der Daten bzw. für eine formatierte Ausgabe. Zudem ist das Importieren von Modulen nichts Schlimmes.

Du solltest auf jeden Fall das Tutorial für Python 2 oder das Tutorial für Python 3 durcharbeiten, je nachdem welche Version du einsetzt.

Re: Frage zu for-schleifen und Listen

Verfasst: Donnerstag 29. August 2013, 16:52
von /me
Malinka hat geschrieben:1. Neue Liste angelegt:
liste1 = []

2. Ans Ende der for-Schleife:
liste1.append(liste)

Das sollte doch reichen, oder? Sieht auf jeden Fall ganz gut aus :wink:
Du solltest dir nur abgewöhnen den Typ der Variablen in deren Namen mit aufzunehmen. Das bringt in den meisten Fällen keine Vorteile. Das kann im Gegenteil sogar von Nachteil sein wenn du mal auf eine andere Datenstruktur umstellst und der Name dann auf einmal irreführend ist.

Re: Frage zu for-schleifen und Listen

Verfasst: Donnerstag 29. August 2013, 19:20
von Hyperion
Ergänzend zu /me: Du solltest Dir auch abgewöhnen, Namen mit Indizes / Nummern zu versehen! Was sagt Dir denn ``liste1``? Dass sie zuerst an etwas gebunden wird? Dass sie irgend wie anders ist als nur ``liste``?

Im Regelfall macht man etwas falsch, wenn man Namen nummeriert! Entweder gibt es einfach einen treffenderen (s. z.B. ``datapool``, ``result`` - wenn es sich denn um ein Ergbnis an sich handelt), oder aber man hat lauter separate Namen a la ``a1``, ``a2``, ..., ``an`` - dann will man stattdessen eine *äußere* Datenstruktur benutzen, wie Du es ja anstrebst.

Re: Frage zu for-schleifen und Listen

Verfasst: Donnerstag 29. August 2013, 19:45
von Malinka
Okay, mit den Bezeichnungen habt ihr absolut recht. :wink:

Jetzt habe ich noch eine anderen Frage. (noch mit den unübersichtlichen Bezeichnungen)

Ich habe also nun eine Liste, die eine bestimmte Anzahl Listen (in meinem Fall jetzt 4) enthält. Nun möchte ich alle gemeinsamen Wörter, die also in jeder "Unterliste" vorkommen, wieder einer neuen Liste hinzufügen. Das muss ja irgendwie einfacher gehen, als nach meiner Variante. Ich muss vermutlich irgendwie eine range festlegen, damit er jeden Listenindex nach dem Vorkommen des Wortes überprüft. Ich bekomme es aber nicht hin

Code: Alles auswählen

liste2 = []
for wort in liste1[0]:
        if wort in liste1[1]:
            if wort in liste1[2]:
                 if wort in liste1[3]
                      liste2.append(wort)
EDIT: Der Code soll also variabler werden, unabhängig von der Zahl der Listen.

Re: Frage zu for-schleifen und Listen

Verfasst: Donnerstag 29. August 2013, 19:49
von BlackJack
@Malinka: Dazu solltest Du Dir mal den Datentyp `set` anschauen. Damit kann man deutlich einfacher und auch effizienter Schnittmengen bilden.

Edit: Und es geht auch ohne das man explizit Schleifen schreiben muss:

Code: Alles auswählen

from operator import and_

# ...

common_words = reduce(and_, word_sets)

Re: Frage zu for-schleifen und Listen

Verfasst: Donnerstag 29. August 2013, 20:41
von Malinka
Okay, mit das mit set habe ich grundsätzlich verstanden. Aber wie lege ich in der for-schleife die range fest? Ich muss ja, um die Schnittmenge zu bilden, z.B. "set1 & set2 & set3 & set4" durchführen. Wie ich anfange, weiß ich, schätze ich:

Code: Alles auswählen

for i in range(len(liste):
    schnittmenge = set(wortliste[i])
# ?????
:

Re: Frage zu for-schleifen und Listen

Verfasst: Donnerstag 29. August 2013, 20:59
von Hyperion
Hui... Du hast - wie fast jeder Anfänger - mal wieder den Anti-Pattern schlecht hin eingebaut:

Code: Alles auswählen

for i in range(len(liste):
    # zugriff auf Elemente via Index: liste[i]
Vergiss sofort wieder, dass so etwas prinzipiell funktioniert :!:

In Python iteriert man *direkt* über Elemente einer Liste (allgemein eines Iterables), wenn man sich für diese interessiert:

Code: Alles auswählen

for words in liste:
    # words ist eine Sub-Liste in Deinem Falle
Und benenne endlich diese ``liste`` um!

Du kannst aus Deiner verschachtelten Listen-Struktur via ``map`` eine Liste von Sets machen:

Code: Alles auswählen

word_sets = map(set, liste)
Danach hat Dir BlackJack ja schon gezeigt, wie man mittels ``reduce`` einfach den Schnitt über alle Mengen bilden kann.

Du kannst Dir natürlich auch sofort Sets von Wörtern bauen - es sei denn, es gibt zu Beginn einen guten Grund dafür, diese erst einmal in einer Liste zu lassen.

Re: Frage zu for-schleifen und Listen

Verfasst: Donnerstag 29. August 2013, 21:02
von cofi
Zuerst solltest du dir `for i in range(len(list))` abgewoehnen, in Python kann man direkt ueber die Elemente iterieren und das will man meist auch. Sollte zusaetzlich noch der Index noetig sein, gibt es `enumerate`.

Hier zwei Ansaetze fuer die Schnittmenge:

Code: Alles auswählen

In [20]: words = [['a', 'b', 'c'], ['a', 'd', 'e'], ['f', 'a', 'g']]

In [21]: word_intersection = reduce(set.intersection, map(set, words))

In [22]: word_intersection
Out[22]: set(['a'])
Oder "manueller"

Code: Alles auswählen

In [23]: word_intersection = set(words[0])

In [24]: for sub_words in words:
   ....:     word_intersection.intersection_update(set(sub_words))
   ....:     

In [25]: word_intersection
Out[25]: set(['a'])
Dein Ansatz funktioniert nicht, weil du immer wieder `schnittmenge` ueberschreibst, statt sie zu aktualisieren.

Re: Frage zu for-schleifen und Listen

Verfasst: Donnerstag 29. August 2013, 21:07
von Hyperion
@cofi: In Deinem zweiten Ansatz könnte man beim zweiten Element in der for-Schleife anfangen ;-)

Re: Frage zu for-schleifen und Listen

Verfasst: Donnerstag 29. August 2013, 21:23
von Malinka
Vielen vielen Dank für die Hilfestellungen. Ich werde mich da morgen weiter mit auseinandersetzen, da mein Kopf langsam ziemlich dröhnt. :P

Re: Frage zu for-schleifen und Listen

Verfasst: Donnerstag 29. August 2013, 21:44
von cofi
Ja, und man koennte einen Iterator benutzen und das erste Set mit `next` initialisieren .. aber ich wollte es einfach halten ;)

Re: Frage zu for-schleifen und Listen

Verfasst: Donnerstag 29. August 2013, 22:48
von Malinka
Okay, habe doch nicht die Finger davonlassen können.
@ cofi Habe jetzt eher deinen konservativeren Vorschlag genommen, da der doch für mich am besten nachvollziehbar ist und es so nach meinem Geschmack angepasst:

Code: Alles auswählen

vergleichsliste = set(wortliste[0])
    for worte in wortliste:
        #Ein Set der Worte aus der ersten "Sub-Liste" wird mit den Sets aus allen "Sub-Listen" verglichen und die Schnittmenge gebildet
        vergleichsliste &= set(worte)
Habe ich die Funktionsweise jetzt richtig verstanden (siehe Kommentar)?

Wahrscheinlich lacht ihr jetzt, aber ich weiß nicht, warum in meinem Code aus &= hier &= gemacht wird...

Re: Frage zu for-schleifen und Listen

Verfasst: Donnerstag 29. August 2013, 23:02
von BlackJack
@Malinka: Das liegt am Forum. Aber nicht nur deswegen solltes Du lieber die Methode verwenden. Da brauchst Du erstens die `worte` nicht in ein `set` umwandeln und zweitens wird nur `set` verwendet das aktualisiert wird, statt in jedem Schleifendurchlauf ein neues `set` mit einem Zwischenergebnis zu erstellen. Und lesbarer ist es auch, weil man bei einem Methodennamen leichter in der Dokumentation suchen kann als bei einem Operator.