如何在不改变其形状的情况下取消嵌套(unlevel)不必要的嵌套列表? (Python)

How to unnest (unlevel) unnecessary nested list without changing its shape? (Python)

这与我在许多线程中发现的完全不同 - 我并不是要使列表平坦但不嵌套级别如下:

[[[3, 3]]] 应该是 [3, 3]

[[[3, 4], [3, 3]]] 应该是 [[3, 4], [3, 3]] 但不是 [3, 4], [3, 3] 也不是 [3, 4, 3, 3] 因为这完全改变了结构。

基本上,我想在循环中断之前的第一次和第二次迭代中降低级别以获得相同的 len(a_list)。但是我的想法有点不对:

此代码适用于除 [[3], [4]] 之外的任何内容。不知道今天出了什么问题,因为它昨天有效。需要一些帮助来更正此功能。现在它 returns [3] 但应该没有变化。

# Unlevel list - reduce unnecessary nesting without changing nested lists structure
def unlevelList(l):
    if len(l) > 0 and isinstance(l, list):
        done = True
        while done == True:
            if isinstance(l[0], list):
                if len(l) == len(l[0]):
                    l = l[0]
                else:
                    l = l[0]
                    done = False
            else:
                done = False
        return l
    else:
        return l

我倾向于用递归来做到这一点:如果对象是长度为1的列表,则剥离外层;然后,递归地取消其所有子级的级别。

def unlevel(obj):
    while isinstance(obj, list) and len(obj) == 1:
        obj = obj[0]
    if isinstance(obj, list):
        return [unlevel(item) for item in obj]
    else:
        return obj

test_cases = [
    [[[3, 3]]],
    [[[3, 4], [3, 3]]],
    [[3], [4]],
    [[[3]]],
    [[[3], [3, 3]]]
]

for x in test_cases:
    print("When {} is unleveled, it becomes {}".format(x, unlevel(x)))

结果:

When [[[3, 3]]] is unleveled, it becomes [3, 3]
When [[[3, 4], [3, 3]]] is unleveled, it becomes [[3, 4], [3, 3]]
When [[3], [4]] is unleveled, it becomes [3, 4]
When [[[3]]] is unleveled, it becomes 3
When [[[3], [3, 3]]] is unleveled, it becomes [3, [3, 3]]

编辑:再次阅读您的问题,我想您可能希望 [[3], [4]] 保持 [[3], [4]]。如果是这样,那么我将要求解释为 "only strip off excess brackets from the top layer; leave inner one-element lists unaffected"。在这种情况下,您不需要递归。去掉最上面的列表,直到你再也不能了,然后 return 它。

def unlevel(obj):
    while isinstance(obj, list) and len(obj) == 1:
        obj = obj[0]
    return obj

test_cases = [
    [[[3, 3]]],
    [[[3, 4], [3, 3]]],
    [[3], [4]],
    [[[3]]],
    [[[3], [3, 3]]]
]

for x in test_cases:
    print("When {} is unleveled, it becomes {}".format(x, unlevel(x)))

结果:

When [[[3, 3]]] is unleveled, it becomes [3, 3]
When [[[3, 4], [3, 3]]] is unleveled, it becomes [[3, 4], [3, 3]]
When [[3], [4]] is unleveled, it becomes [[3], [4]]
When [[[3]]] is unleveled, it becomes 3
When [[[3], [3, 3]]] is unleveled, it becomes [[3], [3, 3]]

我也推荐一个递归解决方案

def unnest(l):
    if isinstance(l, list) and len(l) == 1 and isinstance(l[0], list):
        return unnest(l[0])
    return l

一些测试用例

test_cases = [
    [[[3], [3, 3]]],
    [[[3, 3]]],
    [[[3, 4], [3, 3]]],
    [[3], [4]],
    [[[3]]]
]

for i in test_cases:
    print(unnest(i))

给予

[[3], [3, 3]]
[3, 3]
[[3, 4], [3, 3]]
[[3], [4]]
[3]

这段代码似乎完全符合您的要求。将列表维护为列表(但平坦)。

import itertools

a = [[[[1, 2]]], [[2, 3, 4, 5]], [[[[[[134, 56]]]]]], 9, 8, 0]
res = []

for element in a:
  if isinstance(element, list):
    while len(element) == 1:
      element = list(itertools.chain(*element))
    res.append(element)
  else:
    res.append(element)

print(res)

结果 res[[1, 2], [2, 3, 4, 5], [134, 56], 9, 8, 0]