是否有一种简单的方法(意思是没有滚动自己的排序功能)在Python中对并行列表进行排序而无需不必要的复制?例如:
foo = range(5)
bar = range(5, 0, -1)
parallelSort(bar, foo)
print foo # [4,3,2,1,0]
print bar # [1,2,3,4,5]
我已经看过使用zip
的示例,但如果可以轻松避免将所有数据从并行列表复制到元组列表并再次返回,这似乎很愚蠢。
答案 0 :(得分:6)
这是一个简单的方法:
perm = sorted(xrange(len(foo)), key=lambda x:foo[x])
这会生成一个排列列表 - perm [i]中的值是foo中第i个最小值的索引。然后,您可以按顺序访问这两个列表:
for p in perm:
print "%s: %s" % (foo[p], bar[p])
你需要对它进行基准测试,以确定它是否更有效率 - 我怀疑它是否有很大的不同。
答案 1 :(得分:3)
有简单的方法吗?是。使用zip。
是否有“不使用zip变体的简单方法”?否。
如果你想详细说明你反对使用zip的原因,那将会有所帮助。你要么复制对象,在这种情况下Python会通过引用进行复制,或者你将一些轻量级的东西复制到一个轻量级的元组中,以至于不值得优化。
如果你真的不关心执行速度,但是特别关注内存压力的某些原因,你可以在你的密钥列表上滚动你自己的冒泡排序(或你选择的排序算法),它会交换密钥列表和目标在进行交换时列出元素。我认为这与简单相反,但它肯定会限制你的工作集。
答案 2 :(得分:0)
要实现这一点,您必须实现自己的排序。
但是:不必要的复制是否真的伤害了您的应用程序? Python的一部分通常也会让我觉得效率低下,但它们足以满足我的需求。
答案 3 :(得分:0)
我能想象的任何解决方案都不会从头开始使用索引,或者dict,或其他一些真正不容易为你节省内存的东西。无论如何,使用zip
只会增加内存使用量的常数因子,因此在解决方案之前确保这确实是一个问题是值得的。
如果它确实成为一个问题,可能会有更有效的解决方案。由于foo
和bar
的元素密切相关,您确定它们的正确表示不是元组列表吗?如果你的内存不足,你是否确定它们不应该处于更紧凑的数据结构中,例如numpy数组或数据库(后者真的很擅长这种操作)?
(另外,顺便说一下,itertools.izip
可以为zip
节省一点内存,但是你仍然会以列表形式结束完整的压缩列表作为排序的结果。)