Seite 1 von 2

mehrere Listen durchlaufen

Verfasst: Mittwoch 11. November 2009, 17:59
von Twilo
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

Verfasst: Mittwoch 11. November 2009, 18:04
von cofi
Es gibt `zip`, bzw `itertools.izip`.

Verfasst: Mittwoch 11. November 2009, 18:11
von ms4py
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.

Verfasst: Donnerstag 12. November 2009, 10:13
von Twilo
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

Verfasst: Donnerstag 12. November 2009, 10:45
von Twilo
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

Verfasst: Donnerstag 12. November 2009, 11:07
von cofi
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:

Verfasst: Donnerstag 12. November 2009, 11:12
von Hyperion
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']

Verfasst: Donnerstag 12. November 2009, 11:15
von 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.

Verfasst: Donnerstag 12. November 2009, 12:12
von Twilo
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

Verfasst: Donnerstag 12. November 2009, 12:19
von Zap
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]

Verfasst: Donnerstag 12. November 2009, 12:27
von ms4py
Genau so hab ich mir das vorgestellt (Lösung von "Zap"). :)

Verfasst: Donnerstag 12. November 2009, 12:45
von Hyperion
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?

Verfasst: Donnerstag 12. November 2009, 12:50
von ms4py
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 ;)

Verfasst: Donnerstag 12. November 2009, 12:56
von Hyperion
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 )

Verfasst: Donnerstag 12. November 2009, 12:57
von Twilo
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

Verfasst: Donnerstag 12. November 2009, 12:58
von Hyperion
Jo, danke. Hatte es inzwischen auch kapiert :-)

Ich denke aber auch, dass hier ein dict die richtige Struktur ist.

Verfasst: Donnerstag 12. November 2009, 13:16
von Twilo
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

Verfasst: Donnerstag 12. November 2009, 13:25
von Zap
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

Verfasst: Donnerstag 12. November 2009, 13:43
von Twilo
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

Verfasst: Donnerstag 12. November 2009, 13:54
von pillmuncher
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)))