如何更改 python 中嵌套列表中的每个元素

How can I change each element in a nested list in python

我一直在从事一个使用大嵌套列表的项目。我不能使用递归函数,因为它们会给我最大递归深度错误。我希望能够浏览列表中的每个项目并根据其类型进行更改。这是我希望该程序执行的操作的简化版本。

list_a = ["string", 1.0, 1.0]
list_b = [1.0, "string", 1.0]
list_c = [list_a, list_b]
def Updater(array):
    for elem in array:
        if type(elem) == str:
            print("string")
        if type(elem) == list:
            Updater(elem)
        if type(elem) == float:
            elem /= 2
Updater(list_c)
print(list_c)

我希望它现在将每个整数除以 2,直到嵌套列表中的每个整数都被除以使得嵌套列表不同。由于递归函数给我错误,还有其他方法吗?

对于嵌套对象来说,这并不是真正的递归方法。此外,最好使用 isinstance.
也就是说,您可以使用

list_a = ["string", 1.0, 1.0]
list_b = [1.0, "string", 1.0]
list_c = [list_a, list_b]

def Updater(lst):
    result = []
    for item in lst:
        if isinstance(item, list):
            result.append(Updater(item))
        elif isinstance(item, str):
            #print(item)
            result.append(item)
        elif isinstance(item, (float, int)):
            result.append(item / 2)
    return result

output = Updater(list_c)
print(output)

产生

[['string', 0.5, 0.5], [0.5, 'string', 0.5]]

为避免递归,您需要实现自己的堆栈。这是一个例子。 (我添加了一个 list_d 包含你的 list_c 和一个标量,以显示在不同深度发现的叶元素。)

list_a = ["string", 1.0, 1.0]
list_b = [1.0, "string", 1.0]
list_c = [list_a, list_b]
list_d = [2.0, list_c]


def walk_list(l):

    if not l:
        return

    parent_lists = []
    parent_indices = []

    current_list = l
    current_index = 0

    while True:

        # descend from current position through lists until 
        # leaf element or empty list is reached
        while True:
            val = current_list[current_index]
            if not isinstance(val, list):
                # found leaf element (result of interest)
                yield (val,
                       parent_lists + [current_list],
                       parent_indices + [current_index])
                break
            elif not val:
                # found empty list (ignore)
                break
            else:
                # list to descend into
                parent_indices.append(current_index)
                parent_lists.append(current_list)
                current_list = val
                current_index = 0

        # increment to next position, reascending to parent
        # each time we go off the end of any list
        while True:
            current_index += 1
            if current_index < len(current_list):
                break
            if not parent_lists:
                return
            current_list = parent_lists.pop()
            current_index = parent_indices.pop()


print('Original: ', list_d)
print()

for val, lists, indices in walk_list(list_d):
    print("saw value {} at position {}".format(repr(val), indices))
    if isinstance(val, float):
        lists[-1][indices[-1]] /= 2

print('\nFinal: ', list_d)

给出:

Original:  [2.0, [['string', 1.0, 1.0], [1.0, 'string', 1.0]]]

saw value 2.0 at position [0]
saw value 'string' at position [1, 0, 0]
saw value 1.0 at position [1, 0, 1]
saw value 1.0 at position [1, 0, 2]
saw value 1.0 at position [1, 1, 0]
saw value 'string' at position [1, 1, 1]
saw value 1.0 at position [1, 1, 2]

Final:  [1.0, [['string', 0.5, 0.5], [0.5, 'string', 0.5]]]

从迭代器返回的 lists 是一个越来越深的子列表列表,这些子列表在从原始列表到相关元素的路径中遇到,即 lists[0] 将包含原始列表列表,lists[-1] 是包含相关值的直接父列表。

显然,如果在遍历列表的同时修改列表,您需要注意只修改标量值,而不是通过在任何列表对象中添加或删除值来修改其结构。