无法使用Python

时间:2017-03-08 19:58:56

标签: python arrays recursion

正如标题所述。我试图使用递归迭代列表并删除列表中的任何数字(包括嵌套列表)等于给定的数字。以下是我到目前为止的情况:

def deepRemoveAll(e, L):
    if len(L) == 0:
        return L
    if type(L[0]) == type([]):
        return deepRemoveAll(e, L[0])
    if e == L[0]:
        L.pop(0)
        return deepRemoveAll(e, L)
    if e != L[0]:
        temp = L[0]
        L.pop(0)
        return [temp] + deepRemoveAll(e, L)

print(deepRemoveAll(47, [42, 47, [1, 2, [47, 48, 49], 50, 47, 51], 52]))

代码对我来说似乎完美无瑕,但由于某种原因,该函数返回列表[42,1,2,48,49]。这是不正确的,因为在这种情况下,我需要删除的是包含在其中的任何47,但它也删除了50,51和52.嵌套列表也需要保持不变但这是将所有内容组合成一个而我不能用于我的生活找出原因。

3 个答案:

答案 0 :(得分:3)

这应该有所帮助:

def deep_remove_all(e, a_list):
    res = []
    for item in a_list:
        if isinstance(item, list):
            res.append(deep_remove_all(e, item))
        elif item != e:
            res.append(item)
    return res

您也可以这样写:

def deep_remove_all(e, a_list):
    res = []
    for item in a_list:
        if item == e:
            continue

        res.append( 
            deep_remove_all(e, item)
            if isinstance(item, list) 
            else item
        )

    return res

答案 1 :(得分:2)

看看这两行:

if type(L[0]) == type([]):
    return deepRemoveAll(e, L[0]);

你在这里说的是:

如果列表的第一个元素是一个列表,那么递归该列表并扔掉此列表的其余元素。

例如,如果您有L=[[1,2],3],那么您的if type(L[0]) == type([])检查将返回true,您会说deepRemoveAll(e, [1,2]),并且3已经消失,无论e是什么是

修复您的代码:

只需将return deepRemoveAll(e, L[0]);更改为L[0] = deepRemoveAll(e, L[0]),以便列表的第一个元素在所有47个被移除后自行转换,然后继续使用其余逻辑。

答案 2 :(得分:0)

让我们看看你的代码并找到一些需要解决的问题:

def deepRemoveAll(e, L):
    if len(L) == 0:
            return L;
    if type(L[0]) == type([]):
            return deepRemoveAll(e, L[0]);
    if e == L[0]:
            L.pop(0);
            return deepRemoveAll(e, L);
    if e != L[0]:
            temp = L[0];
            L.pop(0);
            return [temp] + deepRemoveAll(e, L);

print(deepRemoveAll(47, [42, 47, [1, 2, [47, 48, 49], 50, 47, 51], 52]));

我看到的第一件事就是狡辩:type([])。在现代Python中,那是list

但在我们改变之前,我注意到你在L[0]做了很多事情,而且你几乎总是pop。让我们共同点:

def deepRemoveAll(e, L):
    if len(L) == 0: return L

    l0 = L.pop(0)

现在我们已经获得了l0(因此不再重复索引)并且它已经完成了。我们可以在我们决定的时候把它放回去。

if type(l0) == list:

这将修复上面的type([])。但是,如果第一个元素是子列表,我们该怎么办?显然,我们用第一个元素的深度清理版本替换第一个元素:

if type(l0) == list:
    l0 = deepRemoveAll(e, l0)

它仍然是第一个元素,但现在我们知道它很干净。

接下来的步骤是检查l0是否是我们要移除的e。如果是这样,您替换列表的开头 - 您只需返回已清理的剩余部分。这是正确的,并且作为子列表也是互斥的,因此我们可以使用elseelif

elif l0 == e:
    return deepRemoveAll(e, L)

最后,有l0 != e的情况。在这种情况下,我们要清理L的其余部分,并将l0值粘贴在前面。

但等等!这也是我们想要做的事情,在l0是列表的情况下,还记得吗?到目前为止我们所做的一切都是清理l0。

所以让我们脱离if / elif,这样我们就可以将顶级代码(l0是一个列表)与我们没有放入的else代码合并:l0!= e。

return [l0] + deepRemoveAll(e, L)

全部包装:

def deepRemoveAll(e, L):
    if len(L) == 0: return L

    l0 = L.pop(0)

    if type(l0) == list:
        l0 = deepRemoveAll(e, l0)
    elif l0 == e:
        return deepRemoveAll(e, L)

    return [l0] + deepRemoveAll(e, L)