我正在练习拼合嵌套列表。代码在控制台中工作,但它在文件中时不起作用。我不知道是怎么回事。 :(
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
答案 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将执行它。