- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
关于将多个列表的所有元素 append 在一起的方法,有几个 stackoverflow 问题。我没有看到关于这些不同方法的相对性能的明确答案。此外,有时轻微的性能提升是以牺牲一些可读性为代价的,因此了解几种不同的方法会很有用。
任务:给定一个列表,其中包含任意数量的列表,每个列表包含任意数量的元素,形成一个包含所有元素的列表。首先是第一个列表中的所有元素,然后是第二个列表中的所有元素,等等。这是一个浅表追加:如果列表中有一个元素是列表,则不要提取那些单独的元素。例如
append_all([ [11, 12, 13], [21, 22], [31, [320, 329], 33, 34] ])
=>
[11, 12, 13, 21, 22, 31, [320, 329], 33, 34]
最佳答案
以下是将多个列表 append 在一起的几种方法的时间安排。
它们从最快到最慢显示。
Python 2.7(CPython - 在 Autodesk Maya 2014 中运行)、Windows 7 64 位、Intel Core i7-37770K @ 3.5 GHz。
import timeit
def p_timeit_min(msg, expr_str, number, setup):
times = timeit.repeat(expr_str, number=number, setup=setup, repeat=3)
print( '{0:18} => {1:6.3f}'.format( msg, min(times) ))
n = 1000
timeit.repeat('1+1', number=10000) # "dummy" -- I'm in an environment where the first timeit call is erratic in performance.
setup_0 = '; import operator; L1 = list(range(n)); LL = [[10 * x + v for v in L1] for x in range(n)]'
print
p_timeit_min('map+extend 100', 'all = []; map(all.extend, LL)', number=n, setup='n = 100'+setup_0)
p_timeit_min('for+extend 100', """
all = []
for L in LL:
all.extend(L)
""", number=n, setup='n = 100'+setup_0)
p_timeit_min('extend 100', 'all = []; [all.extend(L) for L in LL]', number=n, setup='n = 100'+setup_0)
# reduce with [] initializer, to avoid need to wrap each L in list().
p_timeit_min('reduce+iadd 100 []', 'all = reduce(operator.iadd, LL, [])', number=n, setup='n = 100'+setup_0)
p_timeit_min('filter extend 100', 'all = []; filter( lambda x: False, iter(all.extend(L) for L in LL) )', number=n, setup='n = 100'+setup_0)
# WARNING: If remove "list()" wrapper around "list_", since this version isn't supplying a [] to accumulate the results, iadd will MODIFY the first element of LL, which may not be desired.
p_timeit_min('reduce+iadd 100 list()', 'all = reduce(operator.iadd, (list(list_) for list_ in LL))', number=n, setup='n = 100'+setup_0)
p_timeit_min('chain 100', 'all = list(itertools.chain(*LL))', number=n, setup='n = 100'+setup_0)
p_timeit_min('comprehension 100', 'all = [x for list_ in LL for x in list_]', number=n, setup='n = 100'+setup_0)
p_timeit_min('nested for append 100',
"""
all = []
for L in LL:
for x in L:
all.append(L)
""", number=n, setup='n = 100'+setup_0)
p_timeit_min('sum 100', 'all = sum(LL, [])', number=n, setup='n = 100'+setup_0)
print
p_timeit_min('map+extend 200', 'all = []; map(all.extend, LL)', number=n, setup='n = 200'+setup_0)
p_timeit_min('for+extend 200', """
all = []
for L in LL:
all.extend(L)
""", number=n, setup='n = 200'+setup_0)
p_timeit_min('extend 200', 'all = []; [all.extend(L) for L in LL]', number=n, setup='n = 200'+setup_0)
p_timeit_min('reduce+iadd 200 []', 'all = reduce(operator.iadd, LL, [])', number=n, setup='n = 200'+setup_0)
p_timeit_min('filter extend 200', 'all = []; filter( lambda x: False, iter(all.extend(L) for L in LL) )', number=n, setup='n = 200'+setup_0)
p_timeit_min('reduce+iadd 200 list()', 'all = reduce(operator.iadd, (list(list_) for list_ in LL))', number=n, setup='n = 200'+setup_0)
p_timeit_min('chain 200', 'all = list(itertools.chain(*LL))', number=n, setup='n = 200'+setup_0)
p_timeit_min('comprehension 200', 'all = [x for list_ in LL for x in list_]', number=n, setup='n = 200'+setup_0)
p_timeit_min('nested for append 200', """
all = []
for L in LL:
for x in L:
all.append(L)
""", number=n, setup='n = 200'+setup_0)
p_timeit_min('sum 200', 'all = sum(LL, [])', number=n, setup='n = 200'+setup_0)
print
输出:
map+extend 100 => 0.062
for+extend 100 => 0.064 ** within margin of error of first place, but slower on average
extend 100 => 0.066
reduce+iadd 100 [] => 0.063 ** see "200" case for reason this isn't placed higher in list.
filter extend 100 => 0.078
reduce+iadd 100 list=> 0.105 ** ignore this - use the better "reduce" above.
chain 100 => 0.127
comprehension 100 => 0.250
nested for append 100=>0.672
sum 100 => 1.424
对于 O(n) 阶算法,这些时间大约长 4 倍 -
“200”大小写为 200 x 200,因此元素总数是“100”大小写的 4 倍。
观察:前 5 个变体的性能明显优于 O(n) - 对于 4 倍多的元素,大约长 3 倍。这是因为每个列表都更长;子列表数量增加了 2 倍:
map+extend 200 => 0.187
for+extend 200 => 0.190
extend 200 => 0.194
reduce+iadd 200 [] => 0.204
filter extend 200 => 0.217
reduce+iadd 200 list=> 0.311 ** ignore this - use the better "reduce" above.
chain 200 => 0.426
comprehension 200 => 0.931
nested for append 200=>2.676
sum 200 => 13.432
分析:如果每个列表都有很多元素,前四个解决方案并没有本质上的不同。
嵌套列表理解需要 4 倍的时间(作为最佳解决方案)。另一方面,总 # 个元素仍然是 O(n)。在许多情况下,这是一个足够小的时间值的 4 倍,无关紧要。
结论:如果这是您所处情况的性能关键因素,请将 list.extend
与任何循环方式一起使用,或 reduce(operator.iadd, LL, [])
。亚军选择:itertools.chain
成本为 2 倍,或 [ .. for .. for .. ]
(嵌套列表理解)成本为 4 倍。
注意:这是一个测试,在一台机器上,在一个实现上,Python 2.7。
它假定您有列表并且您需要将结果作为列表;如果您有/需要序列/生成器/迭代器,这可能会改变平衡(可能有利于 itertools.chain)?
TODO:包含许多 SHORT 列表的测试。
关于Python - 将多个列表中的元素 append 在一起的不同技术的相对性能是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20695889/
Racket 的 pict , 有几个 combinators for combining other pictures .这些文档包含一个很好的表格,说明其 *-append 组合器的工作方式: 这
我看过 Insert content into iFrame和他们的 fiddle http://jsfiddle.net/8VP4y/3/提出以下我遇到问题的代码。 我已经为下面的问题创建了一个 j
我有一个显示非常奇怪结果的微基准: @BenchmarkMode(Mode.Throughput) @Fork(1) @State(Scope.Thread) @Warmup(iterations =
我想知道是否有人可以回答我使用 StringBuilder 对象在 java 中执行这些语句中的哪一个会更好: 使用 .append(string1 + string 2) 对比 .append(st
假设我有两个相同类型的流。是否可以将一个流 append 到另一个流而无需事先将它们转换为列表? 例子: Stream ms = ...; Stream ns = ...; return ms.app
我有以下有效的 jQuery 代码,但它让我思考是否可以对正在 append 的内容执行 append 操作,而无需指定我想要 append 的内容。 append().append() 并没有达到目
这是为了显示诊断页面的检查。我有一个 .append(not_ok) 但当 swf 文件加载 100% 时,我想删除 not_ok 附加,然后添加一个 .append(ok)。 function ca
x = [[1,2],[2,3],[10,1],[10,10]] def duplicatingRows(x, l): severity = x[l][1] if severity =
我有一个列表,我正在尝试将数据注入(inject)其中。列表如下所示 data2 = ['TECH2_HELP', 'TECH2_1507', 'TECH2_1189', 'TECH2_4081',
为了有效地进行一些 DOM 操作,我分离了一个元素。在这个过程中,我遇到了一个有趣的情况: var $holder = $("#d"); var $wrapper = $("").css("borde
我遇到了图片在移动设备上加载速度不够快的问题。我的元素有一个图像和一个按钮。单击该按钮时,图像向下滑动,另一幅图像从顶部滑动以取代它。这是代码 html CSS .moveF
我正在编写一个包含 10 个遗愿 list 的简单哈希表。使用内置的 hash() 计算索引,然后对表大小取模。但是,当我尝试将该对象 append 到该索引处的存储桶列表时,它会 append 到每
我是 LISP 的新手,我正在尝试处理类的 cond 语句。目前,我正在尝试检查传递的值是否为列表,如果是,则将字母 d append 到列表中。 这是我的代码: (defun test(L) (li
我正在使用 Jquery 将数据 append 到 div。但是,append 语句之后页面上没有显示任何内容。 我尝试使用 $(window).load 来确保页面已加载,但这仍然不起作用。 HTM
我有以下代码; function SetupDropdowns() { var PrevType; dropdown1 = document.getElemen
我想在 smarty 中创建一个数组并在其中执行 append 功能!就像我在 smarty 模板中声明一个变量(如 {assign var=sizearr value=''} )然后我想在循环中向其
请考虑以下代码片段: var ul = $(".list_b").find("li").remove().end(); $.each(Sites, functi
我的日志记录配置中有两个 appenders。其中之一在 ERROR 事件上发送电子邮件。 一个类,我无法控制,垃圾邮件 ERROR 消息。所以我仍然想要那些消息,但不是在两个 appenders 中
我正在尝试制作 editText,我要在其中插入一些文本。在每三个字符之后,我想插入破折号。 例子: 类型:123 结果:123- 现在当光标在破折号后面并且你按下删除键时,我想删除破折号和破折号
当我尝试 append 简单的“hello”时,它会被 append ,但很快就会自动删除。仅当我在下面给出的表单中使用它时,才会出现此问题,如果删除该表单,则不会出现问题,并且 hello 会正确
我是一名优秀的程序员,十分优秀!