Python:flatten函数在控制台中工作但不在文件中?

时间:2010-07-13 19:53:51

标签: python flatten

我正在练习拼合嵌套列表。代码在控制台中工作,但它在文件中时不起作用。我不知道是怎么回事。 :(

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

5 个答案:

答案 0 :(得分:5)

问题是你的展平功能只会使一个级别变平。 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上调平。 if type(x) != type([])可以是您的基本案例。

答案 1 :(得分: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)

答案 2 :(得分: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 :(得分: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]

没那么多。

答案 4 :(得分:0)

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

E.g。不会在这里工作:

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

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

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将执行它。