2016-10-25 3 views
3

Ich habe eine Liste von Elementen, die sie Mai oder Mai beliebig verschachtelt werden können. Ich möchte eines der Listenelemente ersetzen. Wie auch immer (verschachtelt oder nicht), ich habe die Indexposition des Elements in einer anderen Liste gespeichert.Suchen und Ersetzen eines Elements in einer (möglicherweise) verschachtelten Liste in Python?

Hier ist eine geschachtelte Liste Beispiel, wo ich 'xyz' durch etwas anderes ersetzen möchte, sagen 123. Ich habe die Lage von 'xyz' in loc gespeichert:

find='xyz' 
replace=123 
nested=[['abc',1],['xyz',2]] 
print(loc) # [1,0] 

Mit loc, wie ich 'xyz' für 123 ersetzen kann? Hier

ist ein nicht verschachteltes Beispiel, wo Ich mag würde die gleiche Substitution tun:

unnested=['abc','xyz'] 
print(loc) # [1] 

Wenn loc nur ein Element hat, dann können Sie einfach tun:

*nest,element=loc 
if not nest: 
    unnested[element]=replace 
else: pass # need help with this part 

Gibt es etwas flexibel genug mit beiden Fällen umgehen?

+3

, die nicht eine verschachtelte Liste ist, es ist eine Liste von Tupeln. Tupel sind unveränderlich, so dass Sie das Element im ersten Fall nicht einfach ersetzen können. –

+0

Sie haben Recht, das ist eine Liste von Tupeln, ich habe versucht, eine einfache Struktur zu zeigen, um das Problem zu vermitteln. Das Anzeigen von mehr Nestern würde nur zur Länge von "loc" beitragen. Ich werde dies bearbeiten, um es zu einer Liste von Listen zu machen. – LMc

Antwort

3

Dies ist die gleiche wie die andere Antwort der Fall ist, geht einfach den Pfad in einer funktionellen Art und Weise:

reduce(getitem, loc[:-1], nested)[loc[-1]] = replace 

in Python 3 Sie müssen Import reduce von functools. Und getitem ist von dem operator Modul. Wenn Sie nur Listen haben, können Sie stattdessen list.__getitem__ verwenden.

Erläuterung: reduce beginnt mit nested und ersetzt sie durch getitem(thecurrentvalue, i) für jeden Wert i in loc[:-1]. Wenn zum Beispiel loc[2, 4, 1, 3] ist, dann erhalten Sie getitem(getitem(getitem(nested, 2), 4), 1). Das ist das Gleiche wie nested[2][4][1].

+0

dies funktioniert nur, wenn jede Ebene eine Liste ist, wenn einige Layer Tupel/andere Konstrukte haben, wird dies nicht funktionieren. Wahrscheinlich kein Problem, aber die Frage wurde ursprünglich unter Verwendung von Tupeln veröffentlicht, was für den Anwendungsfall von OP relevant sein könnte. –

+0

@ TadhgMcDonald-Jensen Nun, ich beantworte die Frage so wie es ist. Und der Titel hat schon vor dem Schnitt "list" gesagt. Deines würde auch nicht für dieses Original arbeiten, wie du gesagt hast, es ist sogar etwas unmöglich. Jedenfalls habe ich eine allgemeinere Version hinzugefügt und es sieht schöner aus. Danke :-) –

+0

@StefanPochmann stört es, eine Erklärung dafür zu geben, wie das funktioniert? – LMc

3

ok so loc = [0,1] gegeben würden Sie den Vorgang Vorform wollen:

thing[0][1] = replace 

oder gegeben loc = [1] Sie

thing[1] = replace 

Vorform würde oder wenn wir zu kompliziert Daten hatte und loc = [0,1,2,3,4,5,6,7] würden Sie wollen:

thing[0][1][2][3][4][5][6][7] = replace 

In jedem Fall f rste müssen jede Schicht vor dem letzten Element sehen, die wir in einer for-Schleife wie folgt tun:

*nest,element=[0,1,2,3,4,5,6,7] 
layer = thing #start with the original object 
for i in nest: 
    layer = layer[i] #get an element from this layer 
#now layer == thing[0][1][2][3][4][5][6] 
layer[element] = replace 

Dies funktioniert auch, wenn es in loc da in diesem Fall die for-Schleife über iteriert nur ein Element ist eine leere Sequenz so ist es nicht erforderlich, diesen Fall zu behandeln seperat

+1

Ein Hinweis: Das OP hat die Python-Version nicht spezifiziert (das 'print' mit nur einem Argument wäre gleichwertig, ganz zu schweigen von' __future__' kann es zu einer Funktion auf Py2 machen). '* nest, element = [0,1,2,3,4,5,6,7]' ist nur in Py3, nicht in Py2 erlaubt. Auf Py2, mit einer Quellenliste namens 'foo', könntest du entweder' nest = foo [:] ',' element = nest.pop() 'oder' nest, element = foo [: - 1], foo [ -1] '. – ShadowRanger

+1

Da die Op diese Notation in ihrer Frage verwendet habe, nahm ich an, dass sie in der Version von Python, die sie benutzen, gültig ist;) –

+0

Hoppla! Verpasst das. Mach weiter, Sir! :-) – ShadowRanger

0

Wenn Sie nur Listen mit einem Tupel oder einem einzelnen Element haben, können wir zuerst erkennen, ob eine Liste Tupel enthält und die Lambda-Funktion anwenden, um Elemente wie gewünscht zu ersetzen.

Wenn die Liste verschiedene Arten von Tupeln enthält, müssen wir zusätzliche Logik hinzufügen, um dies zu erkennen.

find='xyz' 
replace=123 
mylist1=[('abc',1),('xyz',2)] # nests could be tuples or lists 
mylist2=['abc','xyz'] 
replace_this = '123' 

for mylist in mylist1,mylist2: 

    for x in mylist: 
     if (x[0],x[1]) in mylist:    
      modified = map(lambda (x, y): (x,y) if x!=find else (replace_this,y) ,mylist) 
      break 
     else:    
      modified = map(lambda x: x if x!=find else replace_this ,mylist) 
      break 

    print "modified list=", modified 

Ausgang:

Python 2.7.9 (default, Dec 10 2014, 12:24:55) [MSC v.1500 32 bit (Intel)] on win32 
Type "copyright", "credits" or "license()" for more information. 
>>> ================================ RESTART ================================ 
>>> 
modified list= [('abc', 1), ('123', 2)] 
modified list= ['abc', '123'] 
>>> 
Verwandte Themen