从嵌套的任意深度列表列表

时间:2015-10-23 13:26:00

标签: python list recursion nested combinations

我已经编写了一个递归函数,它迭代地生成具有N个原子的六边形晶格的可能图案。该函数首先在晶格上选取一个点,移除所有与原点太接近的点,然后将下一个原子放在剩余的有效位点之一上。

此函数返回一个嵌套的列表列表,具体取决于要放置的原子数。

E.g。对于两个原子,它将返回如下列表: configs = [[site1,[valid_sites]],[site2,[valid_sites]],...]

对于三个原子: configs = [[site1,[site2_1,[valid_sites]]],[site1,site2_2,[valid_sites]],...]

最多可达任意深度的原子数。每个站点对象都是一个2d-numpy数组。

现在我需要的是从这个嵌套列表中获得所有有效配置的迭代:

[[site1,valid_sites [0]],[site1,valid_sites [1]],... [site2,valid_sites [0]]]

我尝试过itertools.product(),但这有两个问题。在N = 2的情况下,它将site1视为可迭代的,并通过拆分向量(site1 [0],valid_sites [0])生成笛卡尔积...一个简单的测试也表明它不会处理所需的嵌套方式。

我看了herehere,但这些似乎不需要N深度的一般性,后者也不会编译列表。

这是我对递归函数的尝试:

def expand_list(configs,n,N):
if n<N:
expand_list(configs[n],n+1,N)
else:
return list(itertools.product(*configs))

最好是尝试&#34;不要&#34;循环,然后做笛卡尔积?或者是否有一些可以编写的生成器函数来执行此操作?

1 个答案:

答案 0 :(得分:1)

所以你要做的是删除列表中的最后一项,并用最后一项扩展列表,对吧?

这是一个递归解决方案:

def expand_sites(sites):
    return [getsubsite(site) for site in sites]


def getsubsite(site):
    if len(site) == 1:
        return site
    else:
        return site[:1] + getsubsite(site[1])

这是一个非递归解决方案:

def expand_sites(sites):
    return [getsubsite(site) for site in sites]


def getsubsite(site):
    site = site[:]  # copy the list
    while len(site[-1]) > 1:
       site.extend(site.pop())
    site.extend(site.pop())
    return site

一种非递归解决方案,它改变原始列表而不是创建新列表:

def expand_sites(sites):
    for site in sites:
        while len(site[-1]) > 1:
            site.extend(site.pop())
        site.extend(site.pop())