【问题标题】:Python: flatten function works in console but not in file?Python:flatten 函数在控制台中有效,但在文件中无效?
【发布时间】:2011-03-15 12:45:46
【问题描述】:

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

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

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

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

【问题讨论】:

  • 您是否遇到特定错误,“不起作用”是什么意思?
  • 您发布的缩进没有意义。请仔细检查函数体是否实际缩进。
  • 我第一眼看到你的迭代解决方案被破坏了。我建议你用这个[[[[[[[[[[[[[[[[1]]]]]]]]]]]]]]],2](输出:[1,2])测试你写的任何函数
  • @centr0,您的代码混合了制表符和空格(在编写 Python 时这是一个坏主意,在编写 SO 问题时显然不好) - 我用 8 个空格替换了制表符。你的代码是这样的吗?
  • @Nick T:稍微不那么小气:我记得,首选的方法是使用isinstance(obj, class_or_type) 而不是type(x) == typename,因为isinstance 也会返回True,如果object 是给定类/类型的子类的实例,这通常是所需的行为。此外,基于您可以使用类/类型的元组而不是单个元组这一事实,它似乎更强大。

标签: python flatten


【解决方案1】:

问题是您的 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([]) 可以作为您的基本情况。

【讨论】:

    【解决方案2】:

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

    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)
    

    【讨论】:

    • 嗯...如果其中一个元素是字典或对象会发生什么?
    • 在递归测试中,它只会展平键。至于对象,它取决于它如何以及是否实现 repriter。无论如何都不是一个强大的解决方案,但 OP 的具体要求是处理嵌套列表。
    【解决方案3】:

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

    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

    【讨论】:

      【解决方案4】:

      我认为@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]
      

      没有那么多。

      【讨论】:

        【解决方案5】:

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

        例如不会在这里工作:

        ["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就会执行它。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-05-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-10-01
          相关资源
          最近更新 更多