Liste aus Listen erstellen

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.
abstract
User
Beiträge: 33
Registriert: Mittwoch 14. September 2005, 09:29

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
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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()?
abstract
User
Beiträge: 33
Registriert: Mittwoch 14. September 2005, 09:29

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.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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 ;-)
abstract
User
Beiträge: 33
Registriert: Mittwoch 14. September 2005, 09:29

Hmm,

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

CU
Zuletzt geändert von abstract am Dienstag 28. April 2009, 21:43, insgesamt 2-mal geändert.
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.
abstract
User
Beiträge: 33
Registriert: Mittwoch 14. September 2005, 09:29

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
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

@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?
abstract
User
Beiträge: 33
Registriert: Mittwoch 14. September 2005, 09:29

ü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
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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.
abstract
User
Beiträge: 33
Registriert: Mittwoch 14. September 2005, 09:29

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 ?
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

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.
abstract
User
Beiträge: 33
Registriert: Mittwoch 14. September 2005, 09:29

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
abstract
User
Beiträge: 33
Registriert: Mittwoch 14. September 2005, 09:29

Irgendwie kriege ich es nicht hin, kann mir jemand helfen die liste so zu zerlegen ?

THANX
CU
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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 ;-)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Und nach welcher Regel werden die zu erweiternden Tupel ausgewählt? Nach der Hälfte? Zufall? Andere seltsame Dinge?
Das Leben ist wie ein Tennisball.
abstract
User
Beiträge: 33
Registriert: Mittwoch 14. September 2005, 09:29

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
Benutzeravatar
b.esser-wisser
User
Beiträge: 272
Registriert: Freitag 20. Februar 2009, 14:21
Wohnort: Bundeshauptstadt B.

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
abstract
User
Beiträge: 33
Registriert: Mittwoch 14. September 2005, 09:29

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
Benutzeravatar
b.esser-wisser
User
Beiträge: 272
Registriert: Freitag 20. Februar 2009, 14:21
Wohnort: Bundeshauptstadt B.

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)
Antworten