根据索引列表更改列表元素
Change elements of list based on list of indices
索引列表(称为"indlst"),如[[1,0], [3,1,2]]对应元素[1][0]和[3]给定列表(称为 "lst")的 ][1][2],用于在原始列表中更改它们各自的元素?另请注意,索引指的是嵌套到任意深度的元素。例如,给定
indlst = [[1,0], [3,1,2]]
lst = ["a", ["b","c"], "d", ["e", ["f", "g", "h"]]]
required_output = [lst[1][0],lst[3][1][2]]
输出应对应["b","h"]。我知道我可以通过以下代码片段做到这一点(参见 ):
for i in indlst:
temp = lst
for j in i:
temp = temp[j]
print(temp)
b
h
但是,我需要更改原始列表中的这些元素。例如,将每个访问的元素更改为 "CHANGED":
changed_lst = ["a", ["CHANGED","c"], "d", ["e", ["f", "g", "CHANGED"]]]
只需检查每个序列中最内层的索引 - 当您到达它时,
更改值,而不是深入序列并仅检索元素:
for indices in indlst:
base = lst
for i, index in enumerate(indices):
if i == len(indices) - 1:
base[index] = "CHANGED"
break
base = base[index]
这种替代形式可能更优雅,尽管它只是一回事:
for indices in indlst:
base = lst
for index in indices[:-1]:
base = base[index]
base[indices[-1]] = "CHANGED"
本质上,indlst
中的元素是一个索引列表,用于在 lst
中查找特定元素,因此您可以简单地遍历 indlst
中的元素以查找对lst
中您要更改的项目。
def set_item_by_index_list(index_list, list_to_change, new_val):
l = list_to_change
# the last index in index_list is the actual item so we don't need
# to index into it.
for idx in index_list[:-1]:
l = l[idx]
l[index_list[-1]] = new_val
indlst = [[1,0], [3,1,2]]
lst = ["a", ["b","c"], "d", ["e", ["f", "g", "h"]]]
if __name__ == "__main__":
print lst
set_item_by_index_list(indlst[0], lst, "BEER")
print lst
set_item_by_index_list(indlst[1], lst, "WHISKEY")
print lst
以上代码产生:
['a', ['b', 'c'], 'd', ['e', ['f', 'g', 'h']]]
['a', ['b', 'BEER'], 'd', ['e', ['f', 'g', 'h']]]
['a', ['b', 'BEER'], 'd', ['e', ['f', 'WHISKEY', 'h']]]
另一种无需显式循环即可访问最内层列表的方法。
from functools import reduce
indlst = [[1,0], [3,1,2]]
lst = ["a", ["b","c"], "d", ["e", ["f", "g", "h"]]]
for inds in indllst:
innermost_list = reduce(lambda l, r: l[r], inds[:-1], lst)
innermost_list[inds[-1]] = 'CHANGED'
我的想法
我的解决方案是从最深的元素开始,然后按如下方式返回:
- 将最深的元素插入到第二深的元素中
- 将修改后的第二深元素插入第三深元素
- 等等
执行此操作的一些代码
def set_from_indices(value, indices, array):
for i in reversed(range(len(indices))): # Pulls back the deepest element available each loop
current = array.copy() # Without .copy() any changes to current would also change array.
for index, indice in enumerate(indices):
if index == i: # If we are on the deepest element available this loop
current[indice] = value.copy() if isinstance(value, list) else value # Without the .copy() current[indice] just becomes '...'
value = current.copy() # Make the
break
current = current[indice]
return value
indlst = [[0,1], [0,0,1], [0,0,0,1]]
lst = [[[[4,3],2],1],0]
for indices in indlst:
lst = set_from_indices("CHANGED", indices, lst)
索引列表(称为"indlst"),如[[1,0], [3,1,2]]对应元素[1][0]和[3]给定列表(称为 "lst")的 ][1][2],用于在原始列表中更改它们各自的元素?另请注意,索引指的是嵌套到任意深度的元素。例如,给定
indlst = [[1,0], [3,1,2]]
lst = ["a", ["b","c"], "d", ["e", ["f", "g", "h"]]]
required_output = [lst[1][0],lst[3][1][2]]
输出应对应["b","h"]。我知道我可以通过以下代码片段做到这一点(参见
for i in indlst:
temp = lst
for j in i:
temp = temp[j]
print(temp)
b
h
但是,我需要更改原始列表中的这些元素。例如,将每个访问的元素更改为 "CHANGED":
changed_lst = ["a", ["CHANGED","c"], "d", ["e", ["f", "g", "CHANGED"]]]
只需检查每个序列中最内层的索引 - 当您到达它时, 更改值,而不是深入序列并仅检索元素:
for indices in indlst:
base = lst
for i, index in enumerate(indices):
if i == len(indices) - 1:
base[index] = "CHANGED"
break
base = base[index]
这种替代形式可能更优雅,尽管它只是一回事:
for indices in indlst:
base = lst
for index in indices[:-1]:
base = base[index]
base[indices[-1]] = "CHANGED"
本质上,indlst
中的元素是一个索引列表,用于在 lst
中查找特定元素,因此您可以简单地遍历 indlst
中的元素以查找对lst
中您要更改的项目。
def set_item_by_index_list(index_list, list_to_change, new_val):
l = list_to_change
# the last index in index_list is the actual item so we don't need
# to index into it.
for idx in index_list[:-1]:
l = l[idx]
l[index_list[-1]] = new_val
indlst = [[1,0], [3,1,2]]
lst = ["a", ["b","c"], "d", ["e", ["f", "g", "h"]]]
if __name__ == "__main__":
print lst
set_item_by_index_list(indlst[0], lst, "BEER")
print lst
set_item_by_index_list(indlst[1], lst, "WHISKEY")
print lst
以上代码产生:
['a', ['b', 'c'], 'd', ['e', ['f', 'g', 'h']]]
['a', ['b', 'BEER'], 'd', ['e', ['f', 'g', 'h']]]
['a', ['b', 'BEER'], 'd', ['e', ['f', 'WHISKEY', 'h']]]
另一种无需显式循环即可访问最内层列表的方法。
from functools import reduce
indlst = [[1,0], [3,1,2]]
lst = ["a", ["b","c"], "d", ["e", ["f", "g", "h"]]]
for inds in indllst:
innermost_list = reduce(lambda l, r: l[r], inds[:-1], lst)
innermost_list[inds[-1]] = 'CHANGED'
我的想法
我的解决方案是从最深的元素开始,然后按如下方式返回:
- 将最深的元素插入到第二深的元素中
- 将修改后的第二深元素插入第三深元素
- 等等
执行此操作的一些代码
def set_from_indices(value, indices, array):
for i in reversed(range(len(indices))): # Pulls back the deepest element available each loop
current = array.copy() # Without .copy() any changes to current would also change array.
for index, indice in enumerate(indices):
if index == i: # If we are on the deepest element available this loop
current[indice] = value.copy() if isinstance(value, list) else value # Without the .copy() current[indice] just becomes '...'
value = current.copy() # Make the
break
current = current[indice]
return value
indlst = [[0,1], [0,0,1], [0,0,0,1]]
lst = [[[[4,3],2],1],0]
for indices in indlst:
lst = set_from_indices("CHANGED", indices, lst)