fügt Elemente aus der gemischten Liste in eine neue Liste ein

7

Für ein Textklassifizierungsprojekt (Alter) mache ich eine Teilmenge meiner Daten. Ich habe 3 Listen mit Dateinamen erstellt, sortiert nach Alter. Ich möchte diese Listen mischen und dann 5000 Dateinamen aus jeder gemischten Liste an eine neue Liste anhängen. Das Ergebnis sollte eine Datenteilmenge mit 15000 Dateien sein (5000 10s, 5000 20s, 5000 30s). Darunter kannst du sehen, was ich bisher geschrieben habe. Aber ich weiß, dass random.shuffle keine und ein Objekt vom Typ none zurückgibt ist nicht iterierbar. Wie kann ich dieses Problem lösen?

%Vor%     
Bambi 23.04.2017, 11:27
quelle

4 Antworten

7

Sie haben Recht, dass random.shuffle None zurückgibt. Das liegt daran, dass es sein Listenargument an Ort und Stelle mischt, und es ist eine Python-Konvention, die ein veränderbares Argument verwendet und es mutiert, return None . Sie missverstehen jedoch die random arg zu random.shuffle : Es muss ein Zufallszahlengenerator sein, keine Funktion wie Ihre seed , die immer die gleiche Zahl zurückgibt.

Übrigens können Sie den Standard-Zufallszahlengenerator, der vom Zufallsmodul bereitgestellt wird, mit seiner Funktion seed säen. random.seed akzeptiert ein beliebiges Objekt als Argument, obwohl es üblich ist, ihm eine Zahl oder einen String zu übergeben. Sie können auch None übergeben (was äquivalent dazu ist, dass es überhaupt keinen arg übergeben wird), und es wird den Randomisierer mit der zufälligen Systemquelle versehen (wenn es keine zufällige Systemquelle gibt, dann wird die Systemzeit verwendet) als der Samen). Wenn Sie seed nicht explizit nach dem Import des Zufallsmoduls aufrufen, entspricht das dem Aufruf von seed()

Der Vorteil der Bereitstellung eines Seeds besteht darin, dass jedes Mal, wenn Sie das Programm mit dem gleichen Seed ausführen, die Zufallszahlen, die von den verschiedenen zufälligen Modulfunktionen erzeugt werden, genau gleich sind. Das ist sehr nützlich beim Entwickeln und Debuggen Ihres Codes: Es kann schwierig sein, Fehler aufzuspüren, wenn sich die Ausgabe ständig ändert. :)

Es gibt zwei Möglichkeiten, das zu tun, was Sie wollen. Sie können die Listen mischen und dann die ersten 5000 Dateinamen von ihnen trennen. Oder Sie können die Funktion random.sample verwenden, um 5000 Stichproben zu nehmen. Auf diese Weise müssen Sie nicht die gesamte Liste mischen.

%Vor%

Verwenden von sample

%Vor%

Ich habe keine Geschwindigkeitstests für diesen Code durchgeführt, aber ich vermute, dass sample schneller ist, da nur Elemente zufällig ausgewählt werden müssen und nicht alle Listenelemente verschoben werden müssen. shuffle ist ziemlich effizient, so dass Sie wahrscheinlich keinen großen Unterschied in der Laufzeit feststellen würden, es sei denn, Ihre Teaser-, Tweens- und Thirds-Dateilisten haben jeweils mehr als 5000 Dateinamen.

Beide dieser Schleifen machen data zu einer verschachtelten Liste mit 3 Unterlisten, mit 5000 Dateinamen in jeder Unterliste. Wenn Sie möchten, dass es eine flache Liste von 15000 Dateinamen ist, müssen Sie nur die Methode list.extend anstelle von list.append verwenden. ZB

%Vor%

Oder wir können es mit einem Listenverständnis mit einer doppelten for Schleife tun:

%Vor%

Wenn Sie den Inhalt von data filtern müssen, um Ihre endgültige Dateiliste zu erstellen, besteht die einfachste Möglichkeit darin, dem Listenverständnis eine if -Bedingung hinzuzufügen.

Nehmen wir an, wir haben eine Funktion, die testen kann, ob ein Dateiname einer ist, den wir behalten wollen:

%Vor%

Dann können wir

machen %Vor%

und data enthalten nur die Dateinamen, die den keep_file Test bestehen.

Eine andere Möglichkeit besteht darin, die Dateinamen unter Verwendung eines Generatorausdrucks anstelle eines Listenverständnisses zu erstellen und dann an die integrierte Funktion filter zu übergeben:

%Vor%

data_gen ist selbst ein Iterator. Sie können daraus eine Liste erstellen:

%Vor%

Oder wenn Sie nicht wirklich alle Namen als Sammlung benötigen und sie nur einzeln verarbeiten können, können Sie sie in eine for -Schleife schreiben, wie folgt:

%Vor%

Dies benötigt weniger RAM, aber der Nachteil ist, dass es die Dateinamen "verbraucht". Sobald die for Schleife beendet ist, ist data_gen leer.

Nehmen wir an, Sie haben eine Funktion geschrieben, die aus jeder Datei die gewünschten Daten extrahiert:

%Vor%

Sie könnten eine Liste dieser (filename, age, text) Tupel wie folgt erstellen:

%Vor%

Beachten Sie die Scheibe in meinem ersten Ausschnitt: flist[:5000] . Das nimmt die ersten 5000 Artikel in flist , die Artikel mit den Indizes 0 bis einschließlich 4999. Ihre Version hatte teens[:5001] , was ein Fehler nach dem anderen ist. Slices funktionieren genauso wie Bereiche. Somit liefert range(5000) die 5000 Zahlen von 0 bis 4999. Das funktioniert so, weil Python (wie die meisten modernen Programmiersprachen) Zero-basierte Indexierung verwendet.

    
PM 2Ring 23.04.2017, 11:48
quelle
9

Das erste Problem ist, dass Sie die Liste bestehend aus den drei Elementen [Teens, Tweens, Thirthies] mischen (selbst jedes Element ist eine Liste), anstatt jede Unterliste zu mischen

Zweitens können Sie random.sample anstelle von random.shuffle

verwenden %Vor%

oder als @ JonClements, die in den Kommentaren vorgeschlagen werden, können Sie das Listenverständnis

verwenden %Vor%     
Luchko 23.04.2017 11:39
quelle
6

shuffle gibt None zurück, was nicht iterierbar ist

sollten Sie

tun %Vor%     
Azat Ibrakov 23.04.2017 11:38
quelle
2

random.shuffle ändert sich selbst (macht es gemischt). Sie sehen also so aus:

%Vor%

BTW somelist[:n] wird auf n elements gekürzt, überprüfen Sie dies:

%Vor%     
Make Tips 23.04.2017 11:38
quelle

Tags und Links