1

我正在做一个练习来展平嵌套列表。该代码在控制台中有效,但在文件中时无效。我不知道是怎么回事。:(

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()

我首先尝试递归地解决这个练习,但决定先尝试迭代。

编辑:在文件中执行时,它只打印出原始函数参数 TIA

4

5 回答 5

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--- 您也可以调用 flatten yif type(x) != type([])可以作为您的基本情况。

于 2010-07-13T20:09:29.260 回答
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)
于 2010-07-13T20:27:47.077 回答
0

您的应用程序没有做任何事情。

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

您需要继续展平直到它完成,例如使用递归。很简单,但需要对您的数据进行一次额外的传递: If type(x) == type([]),返回flatten(simple)而不是simple在函数末尾。

于 2010-07-13T20:15:01.190 回答
0

我认为@orangeoctopus 的答案是正确的,但没有抓住“为什么它在控制台中工作”的问题。我来做个猜测:

它在控制台中不起作用。我认为您使用恰好有效的输入子集进行了测试。例如,

>>> 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]

没有那么多。

于 2010-07-13T20:27:09.670 回答
0

我的答案与@DonaldMiner 的答案非常相似(实际上我也是这样开始的),但后来注意到如果列表中的字符串包含"["or "]",它将失败。

例如在这里不起作用:

["Hello", "World", "A", "[Menu]"]

我写了一个类似的函数(稍微复杂一点,如果它不在列表中的字符串中,则只删除[and 。]

from ast import literal_eval
def flatten(to_squash):
    """This will flatten a list, no matter the recursion limit."""
    instring = False
    squashed = []
    index = 0
    print(repr(to_squash))
    for char in repr(to_squash):
        if char == '"' or char == "'":
            instring = not instring
            print(instring, char)
            squashed.append(char)
        elif not instring and char == "[" or not instring and char == "]":
            pass
        else:
            squashed.append(char)
        index += 1

    print("".join([item.strip() for item in squashed]))
    return literal_eval("".join(squashed))

您当然也可以使用eval(),但前提是您没有从 somwhere 读取列表(它是由程序制作的)。否则,有人只要输入一个命令,python就会执行它。

于 2014-05-03T19:58:08.317 回答