如何在python中改变嵌套列表中的每个元素?

问题描述 投票:0回答:1

我一直在做一个使用大的嵌套列表的项目,我不能使用递归函数,因为它们会给我最大的递归深度误差。我不能使用递归函数,因为它们会给我最大的递归深度错误。我希望能够检查列表中的每一个项目,并根据它的类型来改变它。以下是我希望程序所做的简化版本。

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,直到嵌套列表中的每个整数都被除以2,这样嵌套列表就会有所不同。由于递归函数给我带来了错误,是否有其他方法可以做到这一点?

python list loops nested-lists
1个回答
0
投票

为了避免递归,你需要实现自己的栈。 下面是一个例子。 (我在这里添加了一个 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] 是包含相关值的直接父列表。

显然,如果在迭代列表时修改列表,你需要注意只修改标量值,而不是通过追加或删除任何列表对象的值来修改其结构。


0
投票

对于嵌套对象来说,并不是一个真正的绕开递归的方法。此外,最好使用 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]]
© www.soinside.com 2019 - 2024. All rights reserved.