我需要展平一些嵌套列表。在编写了flatten函数之后,我自然会试着看看有多少种方法可以打破它。我终于通过pypy运行了它,并且很高兴地发现,当列表真正深入时,pypy的运行速度明显快于cpython。
然而,我看到一种奇怪的情况,即一个更大,更复杂的列表,具有更多元素的测试实际上比“更简单”列表执行得更快。
测试1,其元素较少,运行速度(使用时间pypy ./script.py)比测试2慢一秒。
def flatten(lol):
if not any([isinstance(i, list) for i in lol]):
return lol
flatter = [i for i in lol if not isinstance(i, list)]
for sublist in lol:
if isinstance(sublist, list):
flatter.extend(sublist)
return flatten(flatter)
def silly(l):
return [l, [l]]
nested_function = [["kaplutis", ["mucus", ["my brain", ["is","filled",["with",["pus",]]]]]], "santa gertrudis",[[[[["innermost",flatten(["in", "func"])]]]]]]
tuples = ["empty tuple retained-->", (), ("2-tuple not flattened",), ("I'm the only thing in this tuple")]
dicts = [{"hip": "hop", "ster": "toad"}]
lone_dict = {"lone": 1, "dict": 2}
silly_list = ["1"]
for i in range(20):
silly_list = silly(silly_list)
# test 1 - only the absurdly nested list
print(len(flatten(silly_list)))
# test 2 - absurdly nested list, with
lol = [nested_function, tuples, dicts, lone_dict, silly_list]
print(len(flatten(lol)))
我唯一可以想到的是,当JIT在第二次测试中处理“silly_list”之前的更简单的嵌套列表时,我遇到了一些意外的优化。
答案 0 :(得分:1)
这种特殊的压扁功能确实击中了cpython和pypy中的各种不良点。
我们在前一段时间在irc上找到了它,修复是为了创建一个完全不同的flatten函数,它在cpython中更快,在pypy上更快
我不记得网址,如果OP提供
会很好基本代码与
一致def flatten(items, akk=None)
if akk is None:
akk = []
for item in items:
if isinstance(item, list):
flatten(item, akk)
else:
akk.append(item)
答案 1 :(得分:0)
答案而非评论以包含代码
很难理解代码的作用。确保它是正确的。稍后优化。你可以测试结果:
def flatten(lst, nonscalar_types=list):
for x in lst:
if isinstance(x, nonscalar_types):
yield from flatten(x) # pep 380
else:
yield x # non-list type
print(sum(1 for _ in flatten(lol)))