Python-如何将多维列表排序为二维列表?

时间:2018-12-05 12:58:57

标签: python list

我如何将多维列表排序为二维列表?

多维输入:[8, [6, 7, [-1], [4, [[10]]], 2], 1]

所需的二维输出:[[8, 1], [6, 7, 2], [-1, 4], [], [10]]

所有相同深度列表项都必须位于同一列表中。

6 个答案:

答案 0 :(得分:2)

这个想法与@TerryA回答中的想法基本相同,但是使用setdefault并在for循环的末尾检查是否添加了深度:

lst = [8, [6, 7, [-1], [4, [[10]]], 2], 1]


def depths(l):
    def flatten(l, start=0, depth={}):

        for e in l:
            if isinstance(e, list):
                flatten(e, start=start + 1, depth=depth)
            else:
                depth.setdefault(start, []).append(e)
         if start not in depth:
            depth[start] = []

    d = {}
    flatten(l, depth=d)

    return [d[i] for i in range(max(d) + 1)]


result = depths(lst)
print(result)

输出

[[8, 1], [6, 7, 2], [-1, 4], [], [10]]

答案 1 :(得分:1)

您也许可以在此处使用defaultdict来测量每个元素的深度以及递归:

from collections import defaultdict
L = [8, [6, 7, [-1], [4, [[10]]], 2], 1]
res = defaultdict(list)
def myfunc(L, depth):
    for i in L:
        if isinstance(i, list):
            myfunc(i, depth+1)
        else:
            res[depth].append(i)

myfunc(L, 0)

然后,defaultdict将如下所示:

defaultdict(<class 'list'>, {0: [8, 1], 1: [6, 7, 2], 2: [-1, 4], 4: [10]})

然后,您需要将defaultdict转换回您想要的内容。请注意,默认字典将不会包含空列表,因为它无法检测到它(即:[[10]][10]都是列表),但是它在范围内有一个缺口(注意defaultdict如何缺少深度3

final = []
for i in range(max(res)+1):
    if i not in res:
        final.append([])
    else:
        final.append(res[i])

print(final)

非常混乱,我确定可以进行改进。

答案 2 :(得分:1)

具有递归且没有任何依赖性的我的选项:

lst = [8, [6, 7, [-1], [4, [[10]]], 2], 1]

def flat_group(lst, deep = 0, res = None):
  if res == None: res = []
  for item in lst:
    if len(res) <= deep: res.append([])
    if not type(item) == list:
      res[deep].append((item))
    else:
      flat_group(item, deep + 1, res)
  return res


print(flat_group(lst))
#=> [[8, 1], [6, 7, 2], [-1, 4], [], [10]]


为了展示它是如何工作的,我将该方法分为两部分:

def flat(lst, deep = 0, res = []):
  for item in lst:
    if not type(item) == list:
      res.append((deep, item))
    else:
      flat(item, deep + 1, res)
  return res

def group(lst):
  flatten = flat(lst)
  max_n = max(flatten)[0]
  res = [[] for _ in range(0,max_n+1)]
  for deep, item in flatten:
    res[deep].append(item)
  return res

print(group(lst))
#=> [[8, 1], [6, 7, 2], [-1, 4], [], [10]]

flat(lst)是一种递归方法,可构建一个简单的元组列表,其中每个元组都包含值和原始列表的深层内容。 因此,呼叫flat(lst)返回:

# [(0, 8), (1, 6), (1, 7), (2, -1), (2, 4), (4, 10), (1, 2), (0, 1)]

然后group(lst)生成一个n+1空子列表的列表,其中n是最大深度,它对flat(lst)的结果进行迭代,并通过索引到正确的子列表。

flat_group(lst)的功能几乎相同。

答案 3 :(得分:0)

您可以通过首先在每个深度生成元素的字典来实现此目的(深度作为该字典中的键,并将该深度的元素列表作为值)。下面的递归函数get_elements_by_depth执行此操作。然后,您所需要做的就是将字典的值展平。 (下面的功能flatten_by_depth会满足您的需求)。

from collections import defaultdict

def get_elements_by_depth(ls, cur_depth, cur_dict):
    """
        returns a dictionary with depth as key and a list of all
        elements that have that depth as value
    """
    for x in ls:
        if isinstance(x, list):
            get_elements_by_depth(x, cur_depth + 1, cur_dict)
        else:
            cur_dict[cur_depth].append(x)
    return cur_dict


def flatten_by_depth(ls):
    """
        returns a list of lists, where the list at index i 
        contains all elements of depth i
    """
    elements_by_depth = get_elements_by_depth(ls, 0, defaultdict(list))
    max_depth = max(elements_by_depth.keys())
    # Since we're using a defaultdict, we don't have to worry about
    # missing keys in elements_by_depth
    return [
        elements_by_depth[i]
        for i in xrange(max_depth + 1)
    ]

> flatten_by_depth([8, [6, 7, [-1], [4, [[10]]], 2], 1])
[[8, 1], [6, 7, 2], [-1, 4], [], [10]]

答案 4 :(得分:0)

其他答案采用的递归方法带有Python规定的递归限制和两次通过的开销。一种更有效的单遍迭代方法是使用列表元组队列和相关深度执行广度优先搜索:

from collections import deque
def flatten(lst):
    output = []
    q = deque([(lst, 0)])
    while q:
        l, depth = q.popleft()
        for i in l:
            if isinstance(i, list):
                q.append((i, depth + 1))
            else:
                while depth >= len(output):
                    output.append([])
                output[-1].append(i)
    return output

这样:

flatten([8, [6, 7, [-1], [4, [[10]]], 2], 1])

返回:

[[8, 1], [6, 7, 2], [-1, 4], [], [10]]

答案 5 :(得分:0)

最近有人发布了一个类似的问题,当我撰写我的答案时,该问题被重复了。所以我想在这里添加答案。

def extract_entries(nested_list, new_list=[]):
    # Add the list of all of the items in <nested_list> that are NOT lists themselves. 
    new_list.append( [ e for e in nested_list if type(e) != list ] )

    # Look at entries in <nested_list> that ARE lists themselves.
    for entry in nested_list:
        if type(entry) == list:
            extract_entries(entry, new_list)

    return new_list

测试:

M = [8, [6, 7, [-1], [4, [[10]]], 2], 1]
print(extract_entries(M))
# Returns: [[8, 1], [6, 7, 2], [-1], [4], [], [10]]