mehrere Listen durchlaufen

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.
Twilo
User
Beiträge: 109
Registriert: Mittwoch 10. Januar 2007, 19:17
Wohnort: Berlin
Kontaktdaten:

Hallo,

ich habe 6 Listen.

names
types
values

names_tmp
types_tmp
values_tmp

die 6 Listen müßte ich dann abgleichen. Die Länge der Listen names, types und values ist immer gleich, sowie die Länge der Listen names_tmp, types_tmp und values_tmp. Die Länge von names und names_tmp bzw. types und types_tmp, etc. kann unterschiedlich sein. die von *_tmp kann jedoch nicht größer sein, als die ohne tmp.

Wie muss ich die Listen am besten durchlaufen, damit ich die Werte (values) abgleichen kann? Die types spielen eigentlich keine Rolle, da diese immer gleich sind.

Beispiel

Code: Alles auswählen

names = ["test1", "test2", "test3"]
types = ["text", "text", "text"]
values = ["1", "2", "3"]
names_tmp = ["test2"]
types_tmp = ["text"]
values_tmp = ["11"]

Code: Alles auswählen

als Ergebnis brauche ich dann folgende Listen
["test1", "test2", "test3"]
["text", "text", "text"]
["1", "11", "3"]
Macht man das am besten mit 2 for Schleifen, oder geht das auch "besser"?

Code: Alles auswählen

for i in range(len(names)):
    for j in range(len(names_tmp)):
        if names[i] == names_tmp[j]:
            values[i] = values_tmp[j]
mfg
Twilo
Zuletzt geändert von Twilo am Donnerstag 12. November 2009, 09:48, insgesamt 1-mal geändert.
[url=http://www.farb-tabelle.de/][b]Farbtabelle[/b][/url]
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Es gibt `zip`, bzw `itertools.izip`.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Um alle möglichen Kombinationen von zwei Listen zu generieren, gibt es ``itertools.product``.

Allerdings ist dies in deinem Fall nicht zu empfehlen, da die quadratische Laufzeit gar nicht nötig ist.
Wähle einfach eine sinnvolle Datenstruktur, z.B. mit Dictionarys:

Code: Alles auswählen

variables = dict()
variables['test1'] = dict()
variables['test1']['type'] = 'text'
variables['test1']['value'] = '1'

vars_tmp = dict()
vars_tmp['test1'] = dict()
vars_tmp['test1']['type'] = 'text'
vars_tmp['test1']['value'] = '11'

for varname in vars_tmp:
    try:
        variables[varname]['value'] = vars_tmp[varname]['value']
    except KeyError:
        pass


Edit: überschriebenes builtin korrigiert


Oder du verwendest Klassen.
Twilo
User
Beiträge: 109
Registriert: Mittwoch 10. Januar 2007, 19:17
Wohnort: Berlin
Kontaktdaten:

Hallo,
cofi hat geschrieben:Es gibt `zip`, bzw `itertools.izip`.
mir ist nicht ganz klar, wie mir das helfen soll

In [1]: zip(["test1", "test2", "test3"], ["test1"])
Out[1]: [('test1', 'test1')]

In [2]: zip(["test1", "test2", "test3"], ["test2"])
Out[2]: [('test1', 'test2')]

In [3]: zip(["test1", "test2", "test3"], ["test3"])
Out[3]: [('test1', 'test3')]

In [4]: zip(["test1", "test2", "test3"], ["test1", "test3"])
Out[4]: [('test1', 'test1'), ('test2', 'test3')]

so ganz kann ich mir daraus kein Reim machen :?

ice2k3 hat geschrieben:Wähle einfach eine sinnvolle Datenstruktur, z.B. mit Dictionarys:

Code: Alles auswählen

variables = dict()
variables['test1'] = dict()
variables['test1']['type'] = 'text'
variables['test1']['value'] = '1'

vars_tmp = dict()
vars_tmp['test1'] = dict()
vars_tmp['test1']['type'] = 'text'
vars_tmp['test1']['value'] = '11'

for varname in vars_tmp:
    try:
        variables[varname]['value'] = vars_tmp[varname]['value']
    except KeyError:
        pass

Oder du verwendest Klassen.
die Datenstruktur erhalte ich von ein er Methode zurück, diese Datenstruktur muss ich dann auch wieder zurück geben.
siehe JavaDoc
ich hole mir die Daten mit getNames(), getTypes() und getValues(), überschreibe die values mit meinen *_tmp und schreibe die Daten dann zurück.

Die names_tmp hat die selben Namen wie bei names bzw. nur Teile davon.

Meine 2 For-Schleifen tun was sie tun sollen, jedoch frage ich mich, ob man das nicht "besser" lösen kann. :)

mfg
Twilo
[url=http://www.farb-tabelle.de/][b]Farbtabelle[/b][/url]
Twilo
User
Beiträge: 109
Registriert: Mittwoch 10. Januar 2007, 19:17
Wohnort: Berlin
Kontaktdaten:

Hallo,

folgendes sollte auch gehen

Code: Alles auswählen

In [1]: for name in names_tmp:
   ....:     values[names.index(name)] = values_tmp[names_tmp.index(name)]
   ....:
   ....:

In [2]: values
Out[2]: ['1', '11', '3']
mfg
twilo
[url=http://www.farb-tabelle.de/][b]Farbtabelle[/b][/url]
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Twilo hat geschrieben:
cofi hat geschrieben:Es gibt `zip`, bzw `itertools.izip`.
mir ist nicht ganz klar, wie mir das helfen soll
Entschuldige, ich hatte das Problem nur ueberflogen :oops:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ich hätte mal das hier anzubieten:

Code: Alles auswählen

In [11]: from itertools import chain, ifilterfalse

In [12]: list(chain(names, ifilterfalse(lambda x: x in names, names_tmp)))
Out[12]: ['test1', 'test2', 'test3']
BlackJack

@Twilo: da hast Du jetzt aber zwei zusätzliche Schleifen in den `index()`-Aufrufen "versteckt", denn die machen ja nichts anderes, als die jeweilige Liste zu durchlaufen, bis sie das Argument gefunden haben.
Twilo
User
Beiträge: 109
Registriert: Mittwoch 10. Januar 2007, 19:17
Wohnort: Berlin
Kontaktdaten:

Hallo,
Hyperion hat geschrieben:Ich hätte mal das hier anzubieten:

Code: Alles auswählen

In [11]: from itertools import chain, ifilterfalse

In [12]: list(chain(names, ifilterfalse(lambda x: x in names, names_tmp)))
Out[12]: ['test1', 'test2', 'test3']
damit bekomme ich immer alle Namen (names enthält alle Namen) zurück.
Wie kann ich damit die entsprechenden Values abändern?

BlackJack hat geschrieben:@Twilo: da hast Du jetzt aber zwei zusätzliche Schleifen in den `index()`-Aufrufen "versteckt", denn die machen ja nichts anderes, als die jeweilige Liste zu durchlaufen, bis sie das Argument gefunden haben.
ist die Frage, ob index() schneller als eine normale for-Schleife ist.

mfg
Twilo
[url=http://www.farb-tabelle.de/][b]Farbtabelle[/b][/url]
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Twilo hat geschrieben:Meine 2 For-Schleifen tun was sie tun sollen, jedoch frage ich mich, ob man das nicht "besser" lösen kann. :)
Bei der Datenbasis spricht ja nichts dagegen das so zu machen.
Wenn du die Daten aber auch in anderen zusammenhängen brauchst würde ich sie auch z.B. über ein dict gruppieren. Die Reihenfolge kann ja immer über die Originalliste wieder hergestellt werden.

Schnelles Beispiel:

Code: Alles auswählen

def group(names, types, values):
    d = {}
    for n, t, v in zip(names, types, values):
        d[n] = {'type': t, 'value': v}   
    return d

orig = group(names, types, values)
tmp = group(names_tmp, types_tmp, values_tmp)

orig.update(tmp)

# updated values
print [orig[_n]['value'] for _n in names]
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Genau so hab ich mir das vorgestellt (Lösung von "Zap"). :)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Twilo hat geschrieben: damit bekomme ich immer alle Namen (names enthält alle Namen) zurück.
Wie kann ich damit die entsprechenden Values abändern?
Dann kapiere ich Dein Problem nicht! Was genau willst Du denn erreichen?
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Hyperion hat geschrieben:
Twilo hat geschrieben: damit bekomme ich immer alle Namen (names enthält alle Namen) zurück.
Wie kann ich damit die entsprechenden Values abändern?
Dann kapiere ich Dein Problem nicht! Was genau willst Du denn erreichen?
Schau dir seine Lösung an mit dem ``index`` oder meine, dann müsste es dir eigentlich klar werden ;)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

ice2k3 hat geschrieben:
Hyperion hat geschrieben:
Twilo hat geschrieben: damit bekomme ich immer alle Namen (names enthält alle Namen) zurück.
Wie kann ich damit die entsprechenden Values abändern?
Dann kapiere ich Dein Problem nicht! Was genau willst Du denn erreichen?
Schau dir seine Lösung an mit dem ``index`` oder meine, dann müsste es dir eigentlich klar werden ;)
Ok, ich glaube ich habs kapiert - auch wenn man das wirklich mal explizit hätte beschreiben können ;-) Damit ist meine Lösung def. mal keine (also eine Un-Lösung :-D )
Twilo
User
Beiträge: 109
Registriert: Mittwoch 10. Januar 2007, 19:17
Wohnort: Berlin
Kontaktdaten:

Zap hat geschrieben:
Twilo hat geschrieben:Meine 2 For-Schleifen tun was sie tun sollen, jedoch frage ich mich, ob man das nicht "besser" lösen kann. :)
Bei der Datenbasis spricht ja nichts dagegen das so zu machen.
Wenn du die Daten aber auch in anderen zusammenhängen brauchst würde ich sie auch z.B. über ein dict gruppieren. Die Reihenfolge kann ja immer über die Originalliste wieder hergestellt werden.

Schnelles Beispiel:

Code: Alles auswählen

def group(names, types, values):
    d = {}
    for n, t, v in zip(names, types, values):
        d[n] = {'type': t, 'value': v}   
    return d

orig = group(names, types, values)
tmp = group(names_tmp, types_tmp, values_tmp)

orig.update(tmp)

# updated values
print [orig[_n]['value'] for _n in names]
ok, ich schau mir das mal genauer an

Hyperion hat geschrieben:
Twilo hat geschrieben: damit bekomme ich immer alle Namen (names enthält alle Namen) zurück.
Wie kann ich damit die entsprechenden Values abändern?
Dann kapiere ich Dein Problem nicht! Was genau willst Du denn erreichen?
ich habe 3 Listen (names, types und values) mit gleicher Länge.
Diese Listen erhalte ich mit Methoden getNames, getTypes und getValues, siehe JavaDoc

Ich möchte die values anhand 3 anderer Listen, die den selben Aufbau haben, jedoch weniger Elemente haben kann, ändern.

Beispiel der Listen

Code: Alles auswählen

names = ["test1", "test2", "test3"]
types = ["text", "text", "text"]
values = ["1", "2", "3"]
names_tmp = ["test2", "test1"]
types_tmp = ["text", "text"]
values_tmp = ["11", "23"]
Bei names_tmp gib t es den Namen test2 mit den dazugehörigen Wert 11 und den Namen test1 mit den Wert 23

als Ergebnis brauche ich dann folgendes

Code: Alles auswählen

names = ["test1", "test2", "test3"]
types = ["text", "text", "text"]
values = ["23", "11", "3"]
mfg
Twilo
[url=http://www.farb-tabelle.de/][b]Farbtabelle[/b][/url]
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Jo, danke. Hatte es inzwischen auch kapiert :-)

Ich denke aber auch, dass hier ein dict die richtige Struktur ist.
Twilo
User
Beiträge: 109
Registriert: Mittwoch 10. Januar 2007, 19:17
Wohnort: Berlin
Kontaktdaten:

Hallo,

ich hatte den Beitrag abgeschickt und dann erst gemerkt, das neue Antworten vorhanden waren. :wink:

Bei der Methode mit den dict muss man jedoch 2 mal das ganze konvertieren, von Listen -> dict -> Listen

Code: Alles auswählen

def group(names, types, values):
    d = {}
    for n, t, v in zip(names, types, values):
        d[n] = {'type': t, 'value': v}   
    return d

def ungroup(d):
    names = []
    types = []
    values = []
    for e in d.keys():
        names.append(e)
        types.append(d[e]["type"])
        values.append(d[e]["value"])
    return names, types, values

names = ["test1", "test2", "test3"]
types = ["text", "text", "text"]
values = ["1", "2", "3"]
names_tmp = ["test2", "test1"]
types_tmp = ["text", "text"]
values_tmp = ["11", "23"]

orig = group(names, types, values)
tmp = group(names_tmp, types_tmp, values_tmp)

orig.update(tmp)

names, types, values = ungroup(orig)

names
types
values

Code: Alles auswählen

In [17]: names
Out[17]: ['test1', 'test3', 'test2']

In [18]: types
Out[18]: ['text', 'text', 'text']

In [19]: values
Out[19]: ['23', '3', '11']
mfg
Twilo
[url=http://www.farb-tabelle.de/][b]Farbtabelle[/b][/url]
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Twilo hat geschrieben:

Code: Alles auswählen

In [17]: names
Out[17]: ['test1', 'test3', 'test2']

In [18]: types
Out[18]: ['text', 'text', 'text']

In [19]: values
Out[19]: ['23', '3', '11']
Die Lösung hat aber nicht mehr die richtige Reihenfolge.

Dann ehr so:

Code: Alles auswählen

def ungroup(g, names):
    return (names, 
            [g[n]["type"] for n in names], 
            [g[n]["value"] for n in names])
Auch nicht super schön aber die Reihenfolge stimmt wenigstens
Twilo
User
Beiträge: 109
Registriert: Mittwoch 10. Januar 2007, 19:17
Wohnort: Berlin
Kontaktdaten:

Hallo,
Zap hat geschrieben:
Twilo hat geschrieben:

Code: Alles auswählen

In [17]: names
Out[17]: ['test1', 'test3', 'test2']

In [18]: types
Out[18]: ['text', 'text', 'text']

In [19]: values
Out[19]: ['23', '3', '11']
Die Lösung hat aber nicht mehr die richtige Reihenfolge.

Dann ehr so:

Code: Alles auswählen

def ungroup(g, names):
    return (names, 
            [g[n]["type"] for n in names], 
            [g[n]["value"] for n in names])
Auch nicht super schön aber die Reihenfolge stimmt wenigstens
die Reihenfolge ist zum Glück egal - die Reihenfolge muss dann aber bei jeder der 3 Listen genauso getauscht sein.

Wobei gegen die gleiche Reihenfolge nichts einzuwenden ist :)

mfg
Twilo
[url=http://www.farb-tabelle.de/][b]Farbtabelle[/b][/url]
Benutzeravatar
pillmuncher
User
Beiträge: 1482
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Ich würde es so machen:

Code: Alles auswählen

def group(ns, ts, vs):
    return dict((n,(n,t,v)) for n,t,v in zip(ns,ts,vs))

def ungroup(d, ns):
    return zip(*(d[n] for n in ns))
Und wenn die Reihenfolge keine Rolle spielt, geht auch das:

Code: Alles auswählen

def ungroup(d):
    return zip(*d.values())
Gruß,
Mick.

*edit*
group geht auch kürzer:

Code: Alles auswählen

def group(ns, ts, vs):
    return dict(zip(ns, zip(ns,ts,vs)))
Zuletzt geändert von pillmuncher am Donnerstag 12. November 2009, 14:13, insgesamt 1-mal geändert.
In specifications, Murphy's Law supersedes Ohm's.
Antworten