Python:flatten函数在控制台有效,但在文件中无效?

1 投票
5 回答
527 浏览
提问于 2025-04-16 01:14

我正在做一个练习,目的是把嵌套的列表变成平坦的列表。代码在控制台里能正常运行,但放到文件里就不行了。我也不知道怎么回事。 :(

def flatten(nested):
    """
            >>> flatten([2, 9, [2, 1, 13, 2], 8, [2, 6]])
            [2, 9, 2, 1, 13, 2, 8, 2, 6]
            >>> flatten([[9, [7, 1, 13, 2], 8], [7, 6]])
            [9, 7, 1, 13, 2, 8, 7, 6]
            >>> flatten([[9, [7, 1, 13, 2], 8], [2, 6]])
            [9, 7, 1, 13, 2, 8, 2, 6]
            >>> flatten([[5, [5, [1, 5], 5], 5], [5, 6]])
            [5, 5, 1, 5, 5, 5, 5, 6]
    """
    simple = []

    for x in nested:
            if type(x) == type([]):
                    for y in x:
                            simple.append(y)
            else:
                    simple.append(x)
    return simple



if __name__ == '__main__':
    import doctest
    doctest.testmod()

我最开始是想用递归的方法来解决这个练习,但后来决定先试试迭代的方法。

补充:在文件中执行时,它只是打印出了原来的函数参数。

5 个回答

0

你的应用程序并不是完全不做事情。

Input:  [3,[5, [5, [1, 5], 5], 5], [5, 6]]
Output: [3, 5, [5, [1, 5], 5], 5 ,  5, 6]

你需要不断地将数据“压平”,直到完成,比如可以使用递归的方法。这很简单,但需要多一次遍历你的数据:如果 type(x) == type([]),那么在函数的最后,返回 flatten(simple) 而不是 simple

3

如果你想要“作弊”,可以这样做:

L = [1, 2, [3, 4], 5, 6, [7, 8, [9, 10, 11]]]
s = repr(L)
s = '[' + s.replace('[','').replace(']','') + ']'
L = eval(s)

我有点好奇,这个“作弊”的方法和“正常”的扁平化操作相比,速度会有多快……


补充:

简单测试显示,这种作弊的方法无论数据复杂度如何,所需时间几乎是固定的,而递归的解决方案所需时间会增加。

对于较大的数据:

作弊: 7.13282388182
递归: 2.84676811407

对于较小的数据:

作弊: 7.08800692623
递归: 0.486098086038

这是我的代码(我真的很想知道在更大的数据集上会怎么样!):

import timeit

L = [1,2,3,
     [46, 100000, 20, 9, 
      [1,2,3, 
       [9, 23, 24, 
        [9, 23, 24, 
         [9, 23, 24, 
          [9, 23, 24, 
           [9, 23, 24, [9, 23, 24, [13], 12],4]]]], 26]]]]

L2 = [1,2,3, [4,5,6]]

def flattencheat(mylist):
    s = repr(L)
    s = '[' + s.replace('[', '').replace(']', '') + ']'
    return eval(s)

def flattencurse(mylist):
    newlist = []
    for val in mylist:
        if not hasattr(val, '__iter__'):
            newlist.append(val)
        else:
            newlist.extend(flattencurse(val))

    return newlist

print "Cheat: ", timeit.timeit('flattencheat(L)', "from __main__ import flattencheat, L", number=100000)
print "Recurse: ", timeit.timeit('flattencurse(L)', 
                                 'from __main__ import flattencurse, L',
                                 number = 100000)
print "Cheat: ", timeit.timeit('flattencheat(L2)', "from __main__ import flattencheat, L2", number=100000)
print "Recurse: ", timeit.timeit('flattencurse(L2)', 
                                 'from __main__ import flattencurse, L2',
                                 number = 100000)
5

问题在于你的 flatten 函数只能把一层的内容压平。doctest 报错的原因是因为它确实出错了,返回的结果和你输入的内容不一样。

File "test.py", line 5, in __main__.flatten
Failed example:
    flatten([[9, [7, 1, 13, 2], 8], [7, 6]])
Expected:
    [9, 7, 1, 13, 2, 8, 7, 6]
Got:
    [9, [7, 1, 13, 2], 8, 7, 6]

你应该考虑使用递归的方法,也就是说,不是直接把 y 加进去,而是对 y 也调用 flatten 函数。if type(x) != type([]) 可以作为你的基本情况。

撰写回答