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

发布于 2024-09-09 04:04:30 字数 906 浏览 2 评论 0原文

我正在做一个练习来展平嵌套列表。该代码在控制台中工作,但在文件中时不起作用。我不知道发生了什么事。 :(

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

I'm doing an exercise to flatten nested lists. The code works in console but it doesn't work when its in a file. I have no idea what's going on. :(

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

I first tried to solve this exercise recursively but decided to try it iterative first.

edit: When executed in the file it just prints out the original function argument
TIA

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

歌枕肩 2024-09-16 04:04:30

问题是你的展平函数只能展平一层。 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([]) 可以是您的基本情况。

The problem is that your flatten function only flattens one level. The reason why doctest is printing out errors is because it is indeed erroring. They are not what you passed in.

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]

You should investigate a recursive approach that instead of appending y--- you call flatten on y as well. if type(x) != type([]) can be your base case.

梦冥 2024-09-16 04:04:30

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

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)

If you want to "cheat" you could do this:

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

I'm kind of curious how fast that would be compared to the "normal" flattening operation...


Edit:

A cursory test shows that the cheating method takes nearly constant time regardless of data complexity, while a recursive solution increases in time.

Larger

Cheat: 7.13282388182
Recurse: 2.84676811407

Smaller

Cheat: 7.08800692623
Recurse: 0.486098086038

Here's my code (and I'm really curious about larger data sets!):

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)
与酒说心事 2024-09-16 04:04:30

您的应用程序并不是什么都不做。

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 位于函数末尾。

Your application is not doing nothing.

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

You need to keep flattening until it completes, e.g. using recursion. Simple but with one extra pass over your data: If type(x) == type([]), return flatten(simple) instead of simple at the end of the function.

披肩女神 2024-09-16 04:04:30

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

没有那么多。

I think that @orangeoctopus's answer is correct, but doesn't capture the "why does it work in the console" question. I'm going to make a guess:

It doesn't work in the console. I think you tested with a subset of the input that happens to work. For example,

>>> flatten([2, 9, [2, 1, 13, 2], 8, [2, 6]])
[2, 9, 2, 1, 13, 2, 8, 2, 6]

works!

But

>>> flatten([[9, [7, 1, 13, 2], 8], [7, 6]])
[9, [7, 1, 13, 2], 8, 7, 6]

does not so much.

迷爱 2024-09-16 04:04:30

我的答案与@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(),但前提是你不从某个地方读取列表(它是由程序创建的),否则,有人只需输入命令,Python就会执行。它。

My answer is pretty similiar to @DonaldMiner's (In fact I started out with that as well), but then noticed that if a string in the list contains "[" or "]", it would fail.

E.g. won't work here:

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

I wrote a similiar function (a little more complex, and only removes the [ and ] if it is not in a string in the list.

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

You could of course also use eval(), but only if you dont read in the list from somwhere (It is made by the program). Otherwise, someone can just enter a command, and python will execute it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文