Seite 1 von 1

set in liste umwandlen und andere Operationen

Verfasst: Donnerstag 17. Juli 2008, 18:13
von klaus
Hi Leute,
ich wollte fragen, ob es möglich ist ein set wieder in eine liste umzuwandeln, und wenn ja, wie.

Außerdem wäre es nett, wenn ihr mir sagen könntet, wie ich es schaffe, in eine Liste aus natürlichen Zahlen (z.B. [1, 2, 3, 8, 9, 10, 11, 12, 34, 35, 36]) immer an den Stellen, an denen zwei nicht aufeinanderfolgenden Zahlen stehen den Wert "True" einzufügen. Das Ergebnis sollte dann so aussehen:
[1, 2, 3, True, 8, 9, 10, 11, 12, True, 34, 35, 36]

Bin für jeden Hilfe dankbar.

Verfasst: Donnerstag 17. Juli 2008, 18:44
von EyDu
Du kannst mit der list-Funktion aus einer Menge wieder eine Liste machen.

Zur zweiten Frage:

Code: Alles auswählen

for a, b in zip(liste, liste[1:]):
    print a, b

Verfasst: Freitag 18. Juli 2008, 17:16
von klaus
Danke für die schnelle Antwort, allerdings habe ich jetzt auch einen anderen Weg gefunden, das Problem zu lösen:

Code: Alles auswählen

def prepare(x):
    for n in x:
        if not n:
            continue
        i = x.index(n) + 1
        try:
            n1 = x[i]
        except IndexError:
            continue
        if n+1 != n1:
            x.insert(i, False)
    return x
Aber ich werde trotzdem mal einen Test machen, ob meine Lösung, bei der ich zuerst wieder den Index ermittle und dann den nachfolgenden Index auslese mehr Resourcen verbraucht, als die Lösung über die Funktion zip().

Verfasst: Freitag 18. Juli 2008, 18:06
von BlackJack
Also ich find's recht unübersichtlich und ausserdem würde ich eher eine neue Liste aufbauen, als die alte zu verändern.

Code: Alles auswählen

def prepare(numbers):
    numbers = iter(numbers)
    a = numbers.next()
    for b in numbers:
        yield a
        if b - a > 1:
            yield False
        a = b
    yield a
Tests:

Code: Alles auswählen

In [157]: list(prepare([]))
Out[157]: []

In [158]: list(prepare([1]))
Out[158]: [1]

In [159]: list(prepare([1,2]))
Out[159]: [1, 2]

In [160]: list(prepare([1,3]))
Out[160]: [1, False, 3]

In [161]: list(prepare([1,3,5]))
Out[161]: [1, False, 3, False, 5]

Verfasst: Sonntag 20. Juli 2008, 13:46
von klaus
Also ehrlichgesagt finde ich meine Lösung jetzt nicht unübersichtlich. Sie ist vielleicht nicht elegant, aber jetzt auch nicht komplett konfus. Sie wird vielleicht dadurch etwas lang, dass ich allein 3 Zeilen brauche um den IndexError abzufangen, der beim letzten Schleifendurchlauf entsteht.

Außerdem muss ich sagen, dass ich noch nicht sehr gut im Umgang mit Python bin und mit dem reservierten Wort "yield" noch nicht gearbeitet habe. Ich kann deine Lösung also leider nicht ganz nachvollziehen, aber ich werde sie mir mal genauer anschauen.

Verfasst: Sonntag 20. Juli 2008, 14:27
von BlackJack
Also ich fand die Lösung so konfus, dass ich sie mir gar nicht richtig angeschaut hatte. Habe ich jetzt nachgeholt und da sprang mich Zeile 5 an: Dir ist klar, das `index()` die Liste wieder von vorne nach dem Element durchsucht, das wir längst "in Händen halten"? Damit hat die Funktion quadratische Laufzeit in Abhängigkeit der Länge der Liste. Zähl den Index besser mit `enumerate()` gleich in der Schleife mit.

Und was sollen die beiden Zeilen 3 und 4? Den Effekt, den die haben, hast Du in der Anforderung nicht beschrieben.

Verfasst: Sonntag 20. Juli 2008, 14:52
von klaus
Ok, den index mitzählen ist möglich, dann muss ich nochmal schauen, wie ich es dann schreibe.
Ohne Zeile 3 und 4 erhalte ich eine Funktion, die nach der ersten Lücke unendlich oft False einfügt. Daher muss ich prüfen ob ich schon ein False eingefügt habe und dann weitergehen.

edit:Ich glaube ich habe jetzt so ungefähr das Prinzip verstanden, wie man mit yield arbeitet. Allerdings weiß ich noch nicht genau, wohin es die Werte zurückgibt. Meine Vermutung ist, dass es genau wie return funktioniert, mit dem einzigen Unterschied, dass es die Funktion nicht beendet und daher beliebig viele Werte zurückgeben kann, die man das mit list() in eine Liste umwandeln und einer Variablen zuweisen kann.

So wie es scheint habe ich es jetzt auch geschafft, die Funktion so zu ergänzen, dass sie mehrfach vorhandene Werte automatisch beseitigt. bis jetzt habe ich das "von Hand" vorgenommen indem ich die liste mit set() in eine Menge umgewandelt habe und dann wieder zurück. In der Funktion muss ich dafür nur eine extra-Abfrage einfügen (Zeile 6 und 7), was wahrscheinlich weniger Rechenleistung in Anspruch nimmt. Meine fertige Funktion sieht dann so aus:

Code: Alles auswählen

def prep(x):
    x.sort()
    x = iter(x)
    a = x.next()
    for b in x:
        if a == b:
            continue
        yield a
        if b - a > 1:
            yield False
        a = b
    yield a

Verfasst: Sonntag 20. Juli 2008, 16:17
von BlackJack
Zu den Zeilen 3 und 4 in Deiner vorherigen Lösung: Ah, dann hatte ich immer noch nicht so ganz verstanden wie's geht. Ich wollte auf die "Sonderbehandlung" von der 0 hinaus:

Code: Alles auswählen

In [28]: prepare([1,3])
Out[28]: [1, False, 3]

In [29]: prepare([0,2])
Out[29]: [0, 2]
Ich weiss nicht, ob Dir diese kleine Anomalie bewusst war/ist.

Verfasst: Sonntag 20. Juli 2008, 19:19
von klaus
Die Anomalie ist mir nicht aufgefallen, allerdings ist sie für mich auch nicht weiter schlimm, da ich eine Codezeile vor dieser Funktion alle Zahlen < 0 aus der Liste lösche.

Verfasst: Sonntag 20. Juli 2008, 19:56
von BlackJack
Bei < 0 kann der Bug noch zuschlagen, ich denke Du meinst <= 0!? :-)

Verfasst: Sonntag 20. Juli 2008, 19:58
von klaus
eig. meinte ich <1 ;)
Allerdings würde es mich trotzdem interessieren, wodurch der bug entsteht.

Verfasst: Sonntag 20. Juli 2008, 20:03
von BlackJack
0 ist "falsch":

Code: Alles auswählen

In [50]: bool(0)
Out[50]: False