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
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
)
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.
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:
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)))