Seite 1 von 2

Liste aus Listen erstellen

Verfasst: Dienstag 28. April 2009, 20:58
von abstract
Hi,

ich habe folgendes problem, ich kriege von einer funktion ein ellenlanges dict zurück und möchte daraus eine schöne liste zusammen basteln.

wenn ich mir die dict.keys() ausgeben lasse, kann ich ja mit liste.append(dict.keys) ja schon eine liste draus basteln.

Das problem ist nun folgendes die werte sehen so aus:

...index1|text1
...index2|text1
...index3|text1
...index4|text1
...index5|text1
...index1|text2
...index2|text2
...index3|text2
...index4|text2
...index5|text2
usw.

ich brauche dann zeilen mit den einzelnen index werten:
also:
[index1,text1,text2], [index2,text1,text2] usw.

Habe schon einiges ausprobiert und das einzige was in die nähe kommt wäre:

Code: Alles auswählen

l = []
for i in range (5):
      l.append(liste[i] + liste[i+5])
dadurch kriege ich aber:
[index1,text1,index1,text2], [index2,text1,index2,text2]

So nun kann ich ja mit del die überflüssigen einträge löschen, aber ich denke dass die cracks hier eine bessere lösung parat haben.

Slices wie liste[1:10:5], haben ja dasselbe problem.
oder kann man es vielleicht direkt aus dem dict machen ?

THANX schon mal
CU

Re: Liste aus Listen erstellen

Verfasst: Dienstag 28. April 2009, 21:11
von Hyperion
abstract hat geschrieben:Hi,

ich habe folgendes problem, ich kriege von einer funktion ein ellenlanges dict zurück und möchte daraus eine schöne liste zusammen basteln.
Kannst Du die Funktion ändern? Das wäre ggf. der bessere Weg!
wenn ich mir die dict.keys() ausgeben lasse, kann ich ja mit liste.append(dict.keys) ja schon eine liste draus basteln.
Also in Python 2.6 erzeugt bereits dict.keys() eine Liste ...
Das problem ist nun folgendes die werte sehen so aus:

...index1|text1
...index2|text1
...index3|text1
...index4|text1
...index5|text1
...index1|text2
...index2|text2
...index3|text2
...index4|text2
...index5|text2
usw.
Das ist das dict oder die Liste aus dict.keys()?

Verfasst: Dienstag 28. April 2009, 21:19
von abstract
naja theoretisch könnte ich das schon, ist halt so ne snmpwalk standard abfrage, die ich eben nur benutze.

benutze python 2.5 und wenn ich eben:

Code: Alles auswählen

        err, results = oSnmpmanager.snmpwalk(["1.3.6.1.2.1.4.20"])
        if (not err):
            print len(results)
            if(results):
                for result in results:
                    oid = result[0]
                    val = result[1]
                    l.append([oid,val])
        else:
            print oSnmpmanager.getLastError()
        print l
krieg ich eben so eine liste.

Verfasst: Dienstag 28. April 2009, 21:34
von Hyperion
resulst ist sicherlich kein dict ... ;-)

Code: Alles auswählen

In [53]: keys
Out[53]: [1, 2, 3]

In [54]: texts
Out[54]: ['text1', 'text2', 'text3']

In [55]: [list(chain([index], texts)) for index in keys]
Out[55]:
[[1, 'text1', 'text2', 'text3'],
 [2, 'text1', 'text2', 'text3'],
 [3, 'text1', 'text2', 'text3']]
Musst noch von itertools chain importieren ...

Geht bestimmt auch noch ausschließlich mit Iteratoren denke ich mal ;-)

Verfasst: Dienstag 28. April 2009, 21:41
von abstract
Hmm,

also print results.keys() geht, ergo ist es ein dict.

CU

Verfasst: Dienstag 28. April 2009, 21:41
von BlackJack
@abstract: Was soll das `oSnmpmanager` am Anfang von dem Namen? Falls das für "o"bject steht, warum steht es dann nicht bei allen anderen Namen auch da? In Python ist nämlich *alles* was man an einen Namen binden kann, ein Objekt.

Man braucht keine Klammern um Bedingungen bei ``if``.

`l` (kleines L) ist ein schlechter Name, weil er nichts aussagt und sehr leicht mit einer 1 (Eins) verwechselt werden kann.

Das ``if results`` sieht überflüssig aus. Oder ist das kein leeres "iterable" wenn es kein Ergebnis gibt?

Statt mit Index auf die beiden Elemente zuzugreifen, kann man auch einfach direkt beide Namen in der ``for``-Schleife verwenden:

Code: Alles auswählen

                for oid, val in results:
                    items.append([oid, val])
Falls die Liste am Anfang immer leer ist, würde sich statt der Schleife auch eine "list comprehension" anbieten.

Und jetzt erklär doch nochmal wie die Liste *wirklich* aussieht und was Du gerne haben möchtest.

Verfasst: Dienstag 28. April 2009, 21:46
von abstract
ja ist ein objekt vom snmpmanager den es im net-snmp gibt.

und das l war nur zum testen.

und das andere ist klar aber nicht mein anliegen.

übrigens results.keys() gibt die liste zurück, also ist es doch ein dict.

CU

Verfasst: Dienstag 28. April 2009, 21:47
von Hyperion
@BlackJack:
Ich steh grad auf dem Schlauch:

Code: Alles auswählen

In [61]: d
Out[61]: {1: 'text2', 2: 'text1'}

In [62]: for foo in d:
   ....:     print foo
   ....:
   ....:
1
2
wenn ich auf ein foo[0] und foo[1] zugreifen könnte, dann müßte der Key des dicts ja aus einem Tupel / Liste bestehen? Oder liege ich da falsch?

Verfasst: Dienstag 28. April 2009, 21:50
von abstract
übrigens bei der lösung müsste ich die keys und texts per hand eintragen was bei einigen hundert nicht grad spaßig wäre !

was ich von dem walk zurück kriege ist ja ne "liste" mit 10 spalten aber mit über hundert reihen.

CU

Verfasst: Dienstag 28. April 2009, 21:51
von Hyperion
abstract hat geschrieben:übrigens bei der lösung müsste ich die keys und texts per hand eintragen was bei einigen hundert nicht grad spaßig wäre !

CU
Meinst Du meine Lösung? Nein müßtest Du nicht. Du musst nur das Tupel / die Liste splitten und jeweils ein set davon bilden. Danach geht's so wie gezeigt.

Verfasst: Dienstag 28. April 2009, 21:53
von abstract
Hmm, okay ist jetzt langsam spät werde es morgen mal versuchen zu implementieren.

THANX

vielleicht hat ja jemand bis dahin auch ne andere idee.

CU

P.S. dass es jetzt aber ein dict ist klar oder ?

Verfasst: Mittwoch 29. April 2009, 00:28
von str1442
Das sieht doch nach einem idealem Job für itertools.groupby aus:

Code: Alles auswählen

In [17]: a = """...index1|text1
...index2|text1
...index3|text1
...index4|text1
...index5|text1
...index1|text2
...index2|text2
...index3|text2
...index4|text2
...index5|text2"""

In [27]: a = "\n".join(line.lstrip(".").strip() for line in a.split("\n"))

In [28]: print a
index1|text1
index2|text1
index3|text1
index4|text1
index5|text1
index1|text2
index2|text2
index3|text2
index4|text2
index5|text2

In [29]: from itertools import groupby

In [30]: from operator import itemgetter

In [31]: key_func = itemgetter(0)

In [44]: print [[key] + [value[1] for value in values] for key, values in groupby(sorted((line.split("|") for line in a.split("\n")), key=key_func), key=key_func)]
[['index1', 'text1', 'text2'], ['index2', 'text1', 'text2'], ['index3', 'text1', 'text2'], ['index4', 'text1', 'text2'], ['index5', 'text1', 'text2']]
Wahlweise kann man dann natürlich einfach ein Dict generieren aus (key, value) Tupeln.

@Hyperion: Du brauchst chain nicht für solch einfache Sachen, du kannst Listen einfach addieren.
wenn ich auf ein foo[0] und foo[1] zugreifen könnte, dann müßte der Key des dicts ja aus einem Tupel / Liste bestehen? Oder liege ich da falsch?
Ja. Sind aber natürlich wegen Listen-sind-veränderlich dann Tupel.

Verfasst: Mittwoch 29. April 2009, 08:37
von abstract
Sieht interessant aus, werde es gleich mal ausprobieren.

Die Liste sieht eigentlich z.B. so aus:

Code: Alles auswählen

a = [(1,1),(2,2),(3,3),(4,4),(5,5),(1,6),(2,7),(3,8),(4,9),(5,10)]
und rauskommen soll:

Code: Alles auswählen

[(1,1,6), (2,2,7), (3,3,8), (4,4,9), (5,5,10)]
etc.

also kann man sich das line etc. sparen.

THANX
CU

Verfasst: Mittwoch 29. April 2009, 10:00
von abstract
Irgendwie kriege ich es nicht hin, kann mir jemand helfen die liste so zu zerlegen ?

THANX
CU

Verfasst: Mittwoch 29. April 2009, 10:04
von Hyperion
abstract hat geschrieben:Sieht interessant aus, werde es gleich mal ausprobieren.

Die Liste sieht eigentlich z.B. so aus:

Code: Alles auswählen

a = [(1,1),(2,2),(3,3),(4,4),(5,5),(1,6),(2,7),(3,8),(4,9),(5,10)]
Das ist aber etwas anderes, als Du oben beschrieben hattest!
und rauskommen soll:

Code: Alles auswählen

[(1,1,6), (2,2,7), (3,3,8), (4,4,9), (5,5,10)]
Also ist die zweite Zahl eines Tupels entscheidend für die Verbindung zwischen zwei Tupeln?
Also quasi:

Code: Alles auswählen

(a, b) (b, c) -> (a, b, c)
Bevor man da Mühe investiert, sollte das nämlich erst einmal klar sein ;-)

Verfasst: Mittwoch 29. April 2009, 10:08
von EyDu
Und nach welcher Regel werden die zu erweiternden Tupel ausgewählt? Nach der Hälfte? Zufall? Andere seltsame Dinge?

Verfasst: Mittwoch 29. April 2009, 10:16
von abstract
also wie schon beschrieben kriege ich ja ne ellenlange doppelliste mit den rückgabewerten eines walks. entscheidend ist der index.

d.h.

es ist quasi ein table mit 10 spalten und x zeilen, wobei die zeilen ja aus dem index und 10 werten bestehen.

die werte laufen aber bei dem walk in 2er gruppen rein und ich will die dann so in die tabelle zerlegen wie ich sie mit nem table view kriege.

Code: Alles auswählen

[(index1, wertx), (index2, wertx), (index3, wertx)... (index50000, wertx), (index1, werty), (index2, werty), (index3, werty).....(index50000, werty)...]
und die liste dann soll ja die tabelle darstellen:

Code: Alles auswählen

[(index1,wertx,werty....), (index2,wertx,werty....), (index3,wertx,werty.....) .... (index50000,wertx,werty....)]
da ich die anzahl der gesamtzeilen auslesen kann, weiß ich ja dass sich z.b. jede 50 stelle ein weiterer wert zu dem index befindet und so füttere ich die 10 werte zu dem einem index.

Sorry wenn es nicht ganz klar wurde.

CU

Verfasst: Mittwoch 29. April 2009, 10:43
von b.esser-wisser
Wäre sowas nicht praktischer?

Code: Alles auswählen

the_data = collections.defaultdict(list)
#...
for oid, val in results:
    the_data[oid].append(val)
# so sieht's dann aus:
the_data = {
    index1:[wertx,werty],
    index2:[wertx,werty],
    index3:[wertx,werty],
    #...
    index50000:[wertx,werty],
    }
hth, Jörg

Verfasst: Mittwoch 29. April 2009, 12:12
von abstract
Cool, klappt wunderbar.

noch ne kleine frage, wenn ich das hier in der sanbox laufen lasse:

Code: Alles auswählen

a = [(1,1),(3,2),(55,3),(64,4),(109,5),(1,6),(3,7),(55,8),(64,9),(109,10),(1,11),(3,12),(55,13),(64,14),(109,15)]

for oid, val in a:
    the_data[oid].append(val) 

print the_data
kriege ich es irgendwie willkürlich sortiert:

Code: Alles auswählen

defaultdict(<type 'list'>, {64: [4, 9, 14], 1: [1, 6, 11], 3: [2, 7, 12], 109: [5, 10, 15], 55: [3, 8, 13]})
ich kanns ja danach sortieren, aber eigentlich müsste es doch schon richtig sortiert rauskommen oder ?

THANX

CU

Verfasst: Mittwoch 29. April 2009, 12:23
von b.esser-wisser
Nö, dictionaries sind unsortiert, d.h. du darfst dich nie auf die Reihenfolge verlassen.
(unnützes 'Insider'-wissen: CPython sortiert dict()s nach den Hash's der Keys - aber das ist implementation defined)