Python排序并行数组到位了吗?

Python排序并行数组到位了吗?,python,algorithm,sorting,Python,Algorithm,Sorting,在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的示例,但是如果可以很容易避免的话,将所有数据从并行列表复制到元组列表然后再复制回来似乎很愚蠢。要实现这一点,您必须实现自己的排序 然而:不必要的复制

在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
的示例,但是如果可以很容易避免的话,将所有数据从并行列表复制到元组列表然后再复制回来似乎很愚蠢。

要实现这一点,您必须实现自己的排序


然而:不必要的复制真的会伤害你的应用程序吗?Python的某些部分也常常让我觉得效率低下,但它们的效率足以满足我的需要。

有没有一种简单的方法?对用拉链

有没有“不使用zip变体的简单方法”?没有

如果您想详细说明为什么您反对使用zip,那会很有帮助。要么复制对象,在这种情况下Python将通过引用进行复制,要么将一些非常轻量级的东西复制到轻量级元组中,以至于不值得优化


如果您真的不关心执行速度,但由于某些原因特别关心内存压力,那么您可以在键列表上滚动您自己的冒泡排序(或您选择的排序算法),在进行交换时,它会交换键列表和目标列表元素。我会称之为easy的反面,但它肯定会限制您的工作集。

我能想象的任何解决方案,除了从头开始引入排序外,都会使用索引、dict或其他不利于节省内存的东西。在任何情况下,使用
zip
只会增加内存使用量的一个常数因子,因此在找到解决方案之前,确保这确实是一个问题是值得的

如果这确实成为一个问题,可能会有更有效的解决办法。由于
foo
bar
的元素关系如此密切,您确定它们的正确表示形式不是元组列表吗?如果内存不足,例如numpy数组或数据库(后者非常擅长这种操作),您确定它们不应该处于更紧凑的数据结构中吗

(顺便提一句,
itertools.izip
可以在
zip
上为您节省一点内存,尽管排序的结果仍然是列表形式的完整压缩列表。)

这里有一个简单的方法:

perm = sorted(xrange(len(foo)), key=lambda x:foo[x])
这将生成一个排列列表-排列[i]中的值是foo中第i个最小值的索引。然后,您可以按顺序访问这两个列表:

for p in perm:
  print "%s: %s" % (foo[p], bar[p])

不过,您需要对它进行基准测试,以确定它是否更高效——我怀疑它会有多大的不同。

您认为这种并行排序会有什么作用?从你的评论中可以看出,它按降序对foo进行排序,按升序对bar进行排序,对foo进行锁定操作。如果最初
foo
[2,4,6,10,8]
bar
[3,7,9,5,1],那么
parallelSort
会给出什么
?@Kenny:bar现在已排序并等于[1,3,5,7,9]。foo是在lockstep中操作的,现在等于[8,2,10,4,6]。我明白你关于避免过早优化的观点,但有时(在这种情况下),我喜欢编写通用代码,并且知道如果我在大型数据集或其他东西上使用它,它将“正常工作”。在这种情况下,我更担心的是内存不足,而不是速度。您自己的分类是否会涉及使用
zip
dict
,等等?不。假设您实现了自己的快速排序-您可以确保在两个列表上进行任何交换。我怀疑在Python中实现的任何并行排序都会占用更多的时间和内存。big-O的速度和空间无法提高,而在纯Python中这样做会增加很多开销。@dimcha,如果您有一个大数据集并且内存不足,解决方案可能是这样的,但可能是使用numpy数组,或
数组.array
或数据库,考虑一下这是否是真正有用的解决办法。只是因为你不能想到一个不使用Zip的简单方法并不意味着没有一个-我的答案。你的答案是另一个名字,所以我站在“没有不使用zip变体的简单方法”后面。这是一个愚蠢的问题,但是,如果在内存中排序本质上是什么元组(sort_值,index)比排序元组(sort_值,target_值)更好,好吧,“按另一个名称压缩”?它当然不是——它与压缩无关,并且根本不修改原始元素。事实上,它甚至不涉及第二个数组。压缩仅仅意味着从两个或更多的源iterable构建一个元组iterable。你认为排序(index,key=foo)在做什么?它构造一个元组列表(foo_val,index),然后对它们进行排序。这与压缩(foo_val,target_val)和排序是无法区分的。如果您想有所不同,请将
range
更改为
xrange
。除非你使用的是Python3.Hm,没错。或者使用.sort而不是sorted,但这会破坏单行程序事实证明,这并不比将它们排序到不合适的位置要好,因为
排序
会贪婪地分配大量内存,例如
排序(范围(10**6),key=lambda x:x)
。(我所说的范围是指xrange,它在python3中被更改)当你这样做时,你会注意到你的RAM中有很大一部分消失了。结果表明,
排序
足够聪明,不会对
范围
进行排序,因此要注意在没有
键=
函数的情况下进行测试。