String in Array ablegen

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
Stefsn
User
Beiträge: 16
Registriert: Dienstag 8. Oktober 2019, 06:12

Hey Leute,

folgendes Problem:

Ich habe einen String, z.B. "Sandra zieht Stefan". Diesen würde ich gerne in ein Array "verlosung" ablegen, um ihn in einer .txt Datei zu speichern. Aber irgendwie bekomme ich das einfach nicht hin. Hat jemand von euch eine Idee? Ich bin mir sicher, das ist super Simpel, aber habe es noch nicht herausgefunden.


Danke euch. :)

Gruß, Stefan
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Stefsn: Die Frage ist komisch. Da braucht man kein ”Array”. Datei im Textmodus öffnen, dabei eine passende Kodierung angeben, und die Zeichenkette reinschreiben.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Stefsn
User
Beiträge: 16
Registriert: Dienstag 8. Oktober 2019, 06:12

Ich bin verwirrt. Ich habe ein Array Namen "zuordnung" und eins mit "teilnehmer" ..

Über den Quellcode :

print("****** Fertig ******")
for i in range(anz_teilnehmer):
if(zuordnung[i] != -1):
print(teilnehmer[i] , "zieht" , teilnehmer[math.ceil(zuordnung[i])]);


Wird mir in der Konsole angezeigt, wer wen gezogen hat. Das möchte ich aber nicht sehen und es in einer .txt abspeichern.

Wie ich es jetzt zu dem was du sagtest umkodieren weiß ich leider nicht. :-/
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Stefsn: Das ist jetzt irgendwie eine andere Frage. In der ursprünglichen Frage hattest Du eine Zeichenkette. Und hast Du hier tatsächlich Arrays? Oder sind das eventuell Listen?

In Python verwendet man nur recht selten Indexwerte für den Zugriff, weil man direkt über Elemente von Sequenzwerten iterieren kann. Wenn man ”parallel” über zwei (oder mehr) iterierbare Objekte laufen will, gibt es die `zip()`-Funktion. Wobei ”parallele” Datenstrukturen auch die Frage aufwerfen warum die überhaupt so gespeichert werden.

`anz_teilnehmer` dürfte redundant sein, denn das ist ja sehr wahrscheinlich das gleiche wie ``len(teilnehmer)``.

An dem Beispiel sieht man auch warum deutschsprachige Bezeichner blöd sind: `teilnehmer` ist sowohl Ein- als auch Mehrzahl, da muss man sich also irgend etwas ausdenken um den Wert für einen Teilnehmer von den der Liste von Teilnehmern unterscheiden zu können.

Bei Bedingungen kommen keine Klammern um die gesamte Bedingung und Zeilen werden nicht mit Semikolons abgeschlossen.

Das Beispiel in Python (ungetestet):

Code: Alles auswählen

    print("****** Fertig ******")
    for participant, assignment in zip(participants, assignments):
        if assignment != -1:
            print(participant, "zieht", participants[math.ceil(assignment)])
Und wenn Du das speichern möchtest, musst Du halt eine Textdatei zum schreiben öffnen, und statt `print()` eine Zeichenkette erstellen, die dann in diese Datei geschrieben wird:

Code: Alles auswählen

    print("****** Fertig ******")
    with open("test.txt", "w", encoding="utf-8") as file:
        for participant, assignment in zip(participants, assignments):
            if assignment != -1:
                file.write(
                    f"{participant} zieht"
                    f" {participants[math.ceil(assignment)]}\n"
                )
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Stefsn
User
Beiträge: 16
Registriert: Dienstag 8. Oktober 2019, 06:12

Hey blackjack!

Danke für deine ausführliche Antwort. Ich denke ich habe das von C++ und anderen Programmiersprachen mitgenommen. Aber gut zu wissen, dann werde ich die Sachen in Zukunft abändern und beachten. :)

noch eine Frage: Beim ausführen des Codes kommt folgender Fehler:

File "/Users/tstefsn/Festplattenspeicher/Wichteln/Ziehung.py", line 98
f"{participant}"
^
SyntaxError: invalid syntax

Siehst du, was da noch abgeändert werden muss? Die variablen passen, die habe ich angepasst und in der Konsole wurde auch das korrekte angezeigt. Das ^ zeigt auf die letzten Anführungszeichen.
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

Edit: ich nehma elles zurück, was hier stand.

Der Syntax-Error kann auch auf die Zeile davor hinweisen. Ohne den Codeabschnitt kann das nieman beantworten.
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Stefsn hat geschrieben: Dienstag 8. Oktober 2019, 19:48

Code: Alles auswählen

  File "/Users/tstefsn/Festplattenspeicher/Wichteln/Ziehung.py", line 98
    f"{participant}"
                       ^
SyntaxError: invalid syntax
Welche Python-Version verwendest du? f-Strings gibt es erst seit Python 3.6. Bei einer älteren Python-Version musst du eine andere Art der Stringformatierung verwenden (mit der format-Methode eines Strings zum Beispiel),
Stefsn
User
Beiträge: 16
Registriert: Dienstag 8. Oktober 2019, 06:12

Yeah. Unfortunately, I am using the Version 3.5

Here is my code so far, however it's not that clean:

Würde ab und zu gerne diese Methode nehmen wo ich nicht immer den Index benötige. Aber habe meistens nicht die Idee, wie das gehen sollte (wahrscheinlich weil ich es vorher noch nie so gemacht habe).

Wie würde es denn bspw. bei diesem Teil klappen?

Code: Alles auswählen

# Function declaration
def reset_probability(participants, amount_no_couples):
    """
    input:
        participants --> All participants
        amount_no_couples --> amount of empty places (no partner)
    output:
        probability --> probability of being drawn
    """
    probability = np.zeros(len(participants));

    for i in range(len(participants)):
        if(participants[i] != "no_couple"):
            probability[i] = 1 / (len(participants) - amount_no_couples);
    return probability;
 

Hier der komplette Code. @me , wie würde ich das in der V3.5 umsetzen können?

Code: Alles auswählen

 
 import numpy as np
import math
import Dice_Beispiel

# Function declaration
def reset_probability(participants, amount_no_couples):
    """
    input:
        participants --> All participants
        amount_no_couples --> amount of empty places (no partner)
    output:
        probability --> probability of being drawn
    """
    probability = np.zeros(len(participants));

    for i in range(len(participants)):
        if(participants[i] != "no_couple"):
            probability[i] = 1 / (len(participants) - amount_no_couples);
    return probability;

#main.py
if __name__ == "__main__":

    # Variable declaration
    participants = ["Lukas","no_couple","Stefan","Michelle","Paul","Gera"];
    faces = np.arange(0, len(participants)) # For checking draw couples
    probability = np.zeros(len(participants)) # Probability-Array of being drawn
    assignments = np.zeros(len(participants)) # Assignment-Array
    check = np.zeros((len(participants),len(participants))) # Chefcl-Array to check distribution of being drawn
    amount_no_couples = 0
    count = 0
    durchgaenge = 0
    wdhs = 10**0 # For testing the distribution of being drawn how often


    assignments[0:] = -1
    
    # Count how many do not have a couple
    for i in range(len(participants)):
        if participants[i] == "no_couple":
            probability[i] = 0
            amount_no_couples = amount_no_couples + 1

    probability = reset_probability(participants, amount_no_couples)

    for _ in range(wdhs):
        probability = reset_probability(participants, amount_no_couples)
        count = 0
        assignments[0:] = -1
        lottery_done = True
        while(lottery_done): # Do it until noone draw themselve or a partner
            lottery_done = False
            # Lose ziehen
            for i in range(len(participants)):
                if(participants[i] != "no_couple"):
                    val = weighted_sections(faces, probability)
                    count = count + 1
                    assignments[i] = math.ceil(val)
                    probability[val] = 0;
                    for k in range(len(participants)):
                        if(probability[k]):
                            probability[k] = 1 / (len(participants) - amount_no_couples - count)


            # Check if someone has drawn themselves
            for i in range(len(participants)):
                if faces[i] == assignments[i]:
                    lottery_done = True
                    count = 0
                    assignments[0:] = -1
                    probability = reset_probability(participants, amount_no_couples)

            # Check if couples draw each other
            durchgaenge = durchgaenge +1;
            for l in range(math.ceil(len(participants)/2)):
                if participants[2*l] != "no_couple" and participants[2*l+1] != "no_couple":
                    diff1 = faces[2*l+1] - assignments[2*l+1]
                    diffm1 = faces[2*l] - assignments[2*l]
                    if diff1 == 1 or diffm1 == -1:
                        #print("couples draw each other")
                        lottery_done = True
                        count = 0
                        assignments[0:] = -1
                        probability = reset_probability(participants, amount_no_couples)

        for i in range(len(participants)):
            if assignments[i] != -1 :
                pruefung[i][math.ceil(assignments[i])] = pruefung[i][math.ceil(assignments[i])] + 1 ;

    # Umwandlung in Prozent

    for m in range(len(participants)):
        for n in range(len(participants)):
            pruefung[m][n] = math.ceil(pruefung[m][n] / wdhs * 100);



    print("****** lottery_done ******")
    for participant, assignment in zip(participants, assignments):
        if assignment != -1:
            print(participant, "zieht", participants[math.ceil(assignment)])



 
Stefsn
User
Beiträge: 16
Registriert: Dienstag 8. Oktober 2019, 06:12

Huurayyy .. Habe es hinbekommen. Habe es jetzt folgendermaßen gelöst. :)

Code: Alles auswählen

    saveFile = open('Zuordnung.txt','w')
    for participant, assignment in zip(participants, assignments):
                if assignment != -1:
                    saveFile.write(participant +
                                    ' zieht ' +
                                    participants[math.ceil(assignment)] +
                                    '\n'
                    )
    saveFile.close()
Benutzeravatar
ThomasL
User
Beiträge: 1378
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

und jetzt noch "with" und f-strings (>= Python 3.6) benutzen:

Code: Alles auswählen

with open('Zuordnung.txt', 'w') as save_file:
    for participant, assignment in zip(participants, assignments):
        if assignment != -1:
            save_file.write(f"{participant} zieht {participants[math.ceil(assignment)]}\n")
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

@Stefsn: ich verstehe nicht, warum Du numpy überhaupt verwendest, weil Du nichts davon wirklich brauchst.

Unabhängig davon sollte `assignments` vom Typ `int` sein, damit das math.ceil überflüssig wird.
In `reset_probability` sind 100% der Strichpunkte überflüssig. Im Rest des Programms benutzt Du doch auch keine. Um die Bedingung bei if-Abfragen gehören keine Klammern. Über einen Index zu iterieren ist ein Anti-Pattern, entweder benutzt Du kein numpy sondern erzeugst Listen:

Code: Alles auswählen

def reset_probability(participants, amount_no_couples):
    """
    input:
        participants --> All participants
        amount_no_couples --> amount of empty places (no partner)
    output:
        probability --> probability of being drawn
    """
    probability = 1 / (len(participants) - amount_no_couples)
    return [
        0 if participant == "no_couple" else probability
        for participant in participants
    ]
oder Du benutzt `numpy`:

Code: Alles auswählen

def reset_probability(participants, amount_no_couples):
    """
    input:
        participants --> All participants
        amount_no_couples --> amount of empty places (no partner)
    output:
        probability --> probability of being drawn
    """
    return (np.array(participants) == "no_couple") * (1 / (len(participants) - amount_no_couples))
In "main" wird probability definiert, nochmal mit 0 gefüllt, dann aber nie benutzt. Die anderen Variablen (bei Dir "Definitionen" genannt) sollten erst dann initialisiert werden, wenn sie gebraucht werden. Dann merk man auch, dass `count` nie gebraucht wird. `probability` wird auch einmal unnötigerweise berechnet, `assignments` unnötigerweise mit -1 gefüllt. Zum Zählen gibt es count.

Wenn Variablen an der richtigen Stelle initialisiert werden, merkt man, dass kaum etwas außerhalb der großen whd-for-Schleife gebraucht wird, und man damit die Schleife viel einfacher in Funktionen aufteilen kann, weil die viel zu lang ist.

Auch bei while-Bedingungen sind Klammern überflüssig. Wenn man einen Dummy-Wert braucht, damit eine while-Schleife losläuft, dann nimmt man eine while-True-Schleife, die mit passender Bedingung per break verlassen wird.

Wenn man tiefer hinein schaut, wird das Chaos noch deutlicher. Du reinitalisierst `count`, `assignments` und `probability` immer, wenn `lottery_done` auf True gesetzt wird, statt am anfang der while-Schleife, wo es hingehört. Damit wandern diese Variablen nocheinmal eine Ebene tiefer, was die Aufteilung in Funktionen nocheinmal vereinfacht.

Bei der dritten for-Schleife innerhalb der while-Schleife verstehe ich nicht, was in dem Fall passiert, wenn Du in der vorgehenden for-Schleife schon assignments resettet hast? Ich hoffe mal, dass Du den Fall gar nicht so behandeln willst, zumal alles, was in dieser Schleife passiert, dann eh unnötig ist, weil es überschrieben wird.
Warum wird weiter gemacht, solange lottery_done True ist? Der Leser würde das Gegenteil erwarten, dass weiter gemacht wird, solange etwas NICHT fertig ist.

Ich frage mich gerade, woher `pruefung` kommt, das heißt aber weiter oben wahrscheinlich `checks´.

Umwandlung in Prozent macht man mit Array-Operationen statt mit for-Schleifen.

Ein Zwischenstand könnte so aussehen (ungetestet):

Code: Alles auswählen

import numpy as np
import math
import Dice_Beispiel

def reset_probability(participants, amount_no_couples):
    """
    input:
        participants --> All participants
        amount_no_couples --> amount of empty places (no partner)
    output:
        probability --> probability of being drawn
    """
    return (np.array(participants) != "no_couple") * (1 / (len(participants) - amount_no_couples))

def generate_assignments(faces, participants, amount_no_couples):
    while True:
        probability = reset_probability(participants, amount_no_couples)
        # Lose ziehen
        assignments = []
        count = 0
        for participant in participants:
            if participant != "no_couple":
                val = weighted_sections(faces, probability)
                count += 1
                assignments.append(math.ceil(val))
                probability[val] = 0
                probability[probability != 0] = 1 / (len(participants) - amount_no_couples - count)

        # Check if someone has drawn themselves
        if any(faces==assignments):
            # Check if couples draw each other
            lottery_done == True
            diff = faces - assignments
            for participant1, participant2, diffm1, diff1 in zip(participants[::2], participants[1::2], diff[::2], diff[1::2]):
                if participant1 != "no_couple" and participant2 != "no_couple":
                    if diff1 == 1 or diffm1 == -1:
                        #print("couples draw each other")
                        lottery_done = False
                        break
            if lottery_done:
                break
    return assignments


def main():
    participants = ["Lukas","no_couple","Stefan","Michelle","Paul","Gera"];
    amount_no_couples = len(participants) - participants.count("no_couple")
    
    faces = np.arange(0, len(participants)) # For checking draw couples
    pruefung = np.zeros((len(participants),len(participants))) # Chefcl-Array to check distribution of being drawn
    wdhs = 10**0 # For testing the distribution of being drawn how often

    for _ in range(wdhs):
        assignments = generate_assignments(faces, participants, amount_no_couples)
        for element, assignment in zip(pruefung, assignments):
            if assignment != -1:
                element[assignment] += 1
    # Umwandlung in Prozent
    pruefung = np.ceil(pruefung / wdhs * 100)

    print("****** lottery_done ******")
    for participant, assignment in zip(participants, assignments):
        if assignment != -1:
            print(participant, "zieht", participants[assignment])

if __name__ == "__main__":
    main()
Antworten