用计数来替换嵌套列表中的元素

时间:2018-11-20 15:59:30

标签: python

我有一个嵌套列表:

x=[[[0, 1, 2], [0, 1, 2]], [[0, 1], [0, 1, 2]], [[0]], [[0, 1], [0, 1, 2, 3, 4]]]

现在,目标是获得具有相同结构但其元素被其“全局”计数数字替换的嵌套列表。因此,所需的输出应如下所示:

y=[[[0, 1, 2], [3, 4, 5]], [[6, 7], [8, 9, 10]], [[11]], [[12, 13], [14, 15, 16, 17, 18]]]

我与它战斗了最后几个小时,但没有成功。

理想情况下,我希望有一个通用的解决方案,能够处理任意深度的嵌套。

任何帮助将不胜感激。预先谢谢你!

2 个答案:

答案 0 :(得分:3)

这是一个递归解决方案,该解决方案就地进行替换并依赖于要替换的元素的type。这个想法是跟踪“全局计数器”并将其传递给递归调用,以便它知道用以下内容替换元素:

x = [[[0, 1, 2], [0, 1, 2]], [[0, 1], [0, 1, 2]], [[0]], [[0, 1], [0, 1, 2, 3, 4]]]

def replace(lst, i):
    for j in range(len(lst)):
        if isinstance(lst[j], list):
            lst[j], i = replace(lst[j], i)
        else:
            lst[j] = i
        i += 1
    return lst, i - 1

replace(x, 0)
print(x)
# [[[0, 1, 2], [3, 4, 5]], [[6, 7], [8, 9, 10]], [[11]], [[12, 13], [14, 15, 16, 17, 18]]]

答案 1 :(得分:2)

这是另一个递归解决方案。它使用itertools.count并建立一个新列表。就个人而言,我希望尽可能避免整数索引。

from itertools import count

def structured_enumerate(lst, counter=None):
    'enumerate elements in nested list, preserve structure'
    result = []
    if counter is None:
        counter = count()

    for x in lst:
        if isinstance(x, list):
            result.append(structured_enumerate(x, counter))
        else:
            result.append(next(counter))
    return result

演示:

>>> x = [[[0, 1, 2], [0, 1, 2]], [[0, 1], [0, 1, 2]], [[0]], [[0, 1], [0, 1, 2, 3, 4]]]
>>> structured_enumerate(x)
[[[0, 1, 2], [3, 4, 5]],
 [[6, 7], [8, 9, 10]],
 [[11]],
 [[12, 13], [14, 15, 16, 17, 18]]]

〜编辑〜

这是尝试与任何可迭代,可索引或不可索引的通用解决方案的尝试,您可以在其中指定要从迭代中排除的可迭代类型。

from itertools import count

def structured_enumerate(iterable, dontiter=(str,), counter=None):
    'enumerate elements in nested iterable, preserve structure'
    result = []
    if counter is None:
        counter = count()

    for x in iterable:
        # check if x should be iterated
        try:
            iter(x)
            is_iterable = True
        except TypeError:
            is_iterable = False

        # strings of length zero and one are a special case
        if isinstance(x, str) and len(x) < 2:
            is_iterable = False

        if is_iterable and not isinstance(x, dontiter):
            subresult = structured_enumerate(x, dontiter, counter)
            result.append(subresult)
        else:
            result.append(next(counter))

    return result

演示:

>>> fuzzy = [{0, 0}, '000', [0, [0, 0]], (0,0), 0]
>>> structured_enumerate(fuzzy)
[[0, 1], 2, [3, [4, 5]], [6, 7], 8]
>>> structured_enumerate(fuzzy, dontiter=())
[[0, 1], [2, 3, 4], [5, [6, 7]], [8, 9], 10]
>>> structured_enumerate(fuzzy, dontiter=(tuple, set))
[0, [1, 2, 3], [4, [5, 6]], 7, 8]