2016-10-25 34 views
3

我有一个项目列表,他们可能或可能不被任意嵌套。我想替换列表中的一个元素。无论哪种方式(嵌套或不),我有元素的索引位置存储在另一个列表中。在Python中查找并替换(可能)嵌套列表中的元素?

这里是一个嵌套列表示例,我想用其他东西代替'xyz',比如123。我已经存储在loc'xyz'位置:

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

使用loc我怎么能代替'xyz'123

下面是一个嵌套的例子,我想这样做相同的替换:

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

如果loc只有一个元素,那么你可以简单地做:

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

有什么足够的灵活性处理这两种情况?

+3

这不是一个嵌套列表,它是一个元组列表。元组是不可变的,所以你不能直接在第一种情况下替换元素。 –

+0

你说得对,这是一个元组列表,我试图展示一个简单的结构来表达这个问题。显示更多的嵌套只会增加“loc”的长度。我将编辑这个列表。 – LMc

回答

3

这并不相同,对方的回答,只是走路的功能时尚的路径:

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

在Python 3,您需要从中导入reducefunctoolsgetitem来自operator模块。如果您只有列表,则可以使用list.__getitem__代替。

说明:reduce开始与nestedgetitem(thecurrentvalue, i)替换它在loc[:-1]每个值i。因此,例如,如果loc[2, 4, 1, 3]那么你得到getitem(getitem(getitem(nested, 2), 4), 1)。这与nested[2][4][1]相同。

+0

这只适用于如果每个级别都是列表的情况,如果某些图层具有元组/其他构造,则这不起作用。可能不是问题,但问题最初是使用元组发布的,因此可能与OP的用例有关。 –

+0

@ TadhgMcDonald-Jensen好吧,我正在回答这个问题。标题在编辑之前已经说过了“列表”。你的这些原创作品也不会工作,就像你说的那样,甚至有点不可能。无论如何,我添加了一个更通用的版本,它看起来更好。谢谢:-) –

+0

@StefanPochmann你介意添加一些解释,说明这是如何工作的? – LMc

3

确定,所以给loc = [0,1]你想预制棒操作:

thing[0][1] = replace 

或给予loc = [1]你会瓶坯

thing[1] = replace 

,或者如果我们有过于复杂的数据和loc = [0,1,2,3,4,5,6,7]你会想:

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

无论如何我们f IRST的需要,我们可以在一个for循环做这样的最后一个元素之前,每一层查找:

*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 

这也适用于当存在loc只有一个项目,因为在这种情况下,对于循环遍历空序列,所以没有必要把这种情况下seperately

+1

注意:OP没有指定Python版本(只有一个参数的'print'在两者上都是等价的,更不用说'__future__'可以使它成为Py2上的一个函数)。 '* nest,element = [0,1,2,3,4,5,6,7]'在Py3中只是合法的,而不是Py2。在Py2上,有一个名为'foo'的源列表,你可以做:'nest = foo [:]','element = nest.pop()'或'nest,element = foo [: - 1],foo [ -1]'。 – ShadowRanger

+1

由于op在他们的问题中使用了这种表示法,我认为它在他们正在使用的python版本中是有效的;) –

+0

糟糕。错过了。继续先生! :-) – ShadowRanger

0

如果您只有列表具有元组或单个元素,我们可以首先检测列表是否具有元组,并应用lambda函数根据需要替换元素。

如果列表具有不同类型的元组,我们需要添加额外的逻辑来识别它。

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 

输出:

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'] 
>>>