Zwei Zeilen aus datei zu einem Dictionary verarbeiten

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
Wohnbus Altano
User
Beiträge: 1
Registriert: Dienstag 8. November 2016, 20:38

Hallo,
ich habe das Problem dass ich nicht rausbekomme wie ich zwei Zeilen einer Datei zu einem Wertepaar verarbeite.

Code: Alles auswählen

W={}
File=open ("/storage/emulated/0/qpython/Wurzel.txt","r")
for wert in File:
    Zahl=wert.strip ()
    ?
    W.update({Zahl:????})
Die Txt Datei: Der Code sieht bisher so aus de verarbeitungsteil ist auch schon geschrieben.
Die Zeile wo das Fragezeichen steht weiß ich nicht.
Danke für eure Hilfe.

LG Altano
BlackJack

@Wohnbus Altano: Wenn Du zwei Zeilen hast und die etwas unterschiedliches bedeuten, dann solltest Du keine Schleife schreiben die mit jeder Zeile etwas macht, und zwar das gleiche. Öffne die Datei und lass Dir die jeweilige Zeile durch einen `next()`-Aufruf mit dem Dateiobjekt als Argument geben.

Die Namen sind nicht gut gewählt. Einbuchstabige Namen sind selten beschreibend genug. Die Schreibweise entspricht auch nicht dem Style Guide for Python Code.

`update()` ist hier die falsche Methode. Um *ein* Schlüssel/Wert-Paar hinzuzufügen würde man nicht erst umständlich ein neues Wörterbuch mit diesem Paar erstellen und an die `update()`-Methode übergeben, sondern mit der []-Syntax eben diesem einen Schlüssel den Wert zuordnen.
heiner88
User
Beiträge: 65
Registriert: Donnerstag 20. Oktober 2016, 07:29

Du kannst auch die Datei als Ganzes einlesen und in eine Liste umwandeln.
Danach die Liste in ein Dict umwandeln.

Code: Alles auswählen

with open(...) as file:
     liste = file.read().splitlines()

print(liste)
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@heiner88: wenn Du eine Schleife über ein File-Objekt durch eine Schleife über eine Liste ersetzt, bist Du noch nicht wirklich weiter.

@Wohnbus Altano: es gibt verschiedene Möglichkeiten, jeweils zwei Zeilen zu Paaren zu kombinieren. Z.B. so:

Code: Alles auswählen

roots = {}
with open(FILENAME) as lines:
    for key, value in zip(lines, lines):
        roots[key.strip()] = value.strip()
oder per Dictionary-Comprehension:

Code: Alles auswählen

with open(FILENAME) as lines:
    roots = {key.strip(): value.strip() for key, value in zip(lines, lines)}
heiner88
User
Beiträge: 65
Registriert: Donnerstag 20. Oktober 2016, 07:29

Auf eine Liste kann ich wahlfrei zugreifen, auf eine Datei nur sequentiell.
Natürlich sind deine Lösungen eleganter, aber wie soll da ein Anfänger draufkommen.

Code: Alles auswählen

#python3
with open("wurzel.txt") as file:
     liste = file.read().splitlines()
print(liste)

i = 0
w = {}
while i+1 < len(liste):
    w[liste[i]] = liste[i+1]
    i = i + 2
     
print(w)
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@heiner88: so wie Du schreibst, schreibt man in Programmiersprachen, die keine Iteratoren kennen, z.B. BASIC oder C.
Ich behaupte ja nicht, dass ein Anfänger auf meine Lösung kommt, deshalb zeige ich sie ja hier. Aber ein Anfänger soll halt lernen, wie man solche oder ähnliche Probleme mit dem typischen Muster löst. Liste, while-Schleife und Index ist keine Lösung, weil sie die Sprache nicht nutzt, so lernt der Anfänger kein Python, sondern BASIC mit der Syntax von Python.
heiner88
User
Beiträge: 65
Registriert: Donnerstag 20. Oktober 2016, 07:29

Jetzt bin ich noch auf die next()-Lösung von Blackjack gespannt.
BlackJack

Code: Alles auswählen

#!/usr/bin/env python
from __future__ import absolute_import, division, print_function


def main():
    with open('wurzel.txt') as lines:
        mapping = {(next(lines)).rstrip(): next(lines).rstrip()}
    print(mapping)


if __name__ == '__main__':
    main()
Wobei für ein Schlüssel/Wert-Paar ein Wörterbuch nicht so wirklich sinnvoll ist. Und wenn in den Zeilen Zahlendarstellungen stehen, man die vielleicht auch in tatsächliche Zahltypen umwandeln möchte.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1017
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Ich hatte mal ein bisschen mit Generatoren experimentiert. Ich wollte etwas wie eine Eierlegende Wollmilchsau.

http://pastebin.com/bra6GUxH

Code: Alles auswählen

# This could be improved.
 
def chunker(iterable, num):
    """
   Returns an generator which yields the available chunks.
   If the last chunk is incomplete, it'll be cut off.
   """
    iterator = iter(iterable)
    while iterator:
        ret = []
        for _ in range(num):
            try:
                ret.append(next(iterator))
            except StopIteration:
                return
        else:
            yield ret
Hier ein Beispiel:

Code: Alles auswählen

s = 'Line 1\nLine 2\nLine 3\nLine 4\nLine 5\nLine 6'
ret = {}
for k, v, in chunker(s.splitlines(), 2): #splitlines ist hier wichtig
    ret.update({k.strip(): v.strip()})

# {'Line 1': 'Line 2', 'Line 3': 'Line 4', 'Line 5': 'Line 6'}
Mit Dateien: example.txt

Code: Alles auswählen

Foo
42
Bar
43
FooBar
45
BarFoo
55
Missing!!!!!!

Code: Alles auswählen

with open('example.txt') as fd:
    ret = {}
    for k, v in chunker(fd, 2):
        ret.update({k.strip(): v.strip()})

# ret: {'Bar': '43', 'BarFoo': '55', 'Foo': '42', 'FooBar': '45'}
Missing!!!!!! taucht nicht auf, da danach StopIteration ausgelöst wird, obwohl die Anzahl der Elemente noch nicht erreicht ist.
Je nach Anforderung kann es aber auch gut sein, wenn man eine Exception auslöst. Kommt halt drauf an wie sauber die Daten sind, die rein kommen.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@DeaD_EyE: um ein Element eines Wörterbuchs zu setzen, nimmt man nicht update sondern die Eckigen Klammern. Bei Deinem chunker ist die while-Bedingung immer erfüllt, weil ein Iterator immer "wahr" ist. `while True:` wäre daher klarer. Einen else-Block bei einem for ohne break ist witzlos.
Da eine StopIteration eine "normale" Exception für Generatoren ist, braucht man die erst gar nicht abzufangen:

Code: Alles auswählen

def chunker(iterable, num):
    """
    Returns an generator which yields the available chunks.
    If the last chunk is incomplete, it'll be cut off.
    """
    iterator = iter(iterable)
    while True:
        yield [next(iterator) for _ in range(num)]
Antworten