例如
X=[5,6,2,3,1]
Y=[7,2,3,4,6]
我对 X 进行排序:
X=[1,2,3,5,6]
但我希望对 Y 应用相同的相对排序,以便数字保持与以前相同的相对位置:
Y=[6,3,4,7,2]
我希望这是有道理的!
通常,您为此做一个zip
-sort
unzip
>>> X = [5,6,2,3,1]
>>> Y = [7,2,3,4,6]
现在将它们排序在一起:
>>> sorted(zip(X,Y))
[(1, 6), (2, 3), (3, 4), (5, 7), (6, 2)]
zip(*...)
将其与“解压缩”( )配对
>>> zip(*sorted(zip(X,Y)))
[(1, 2, 3, 5, 6), (6, 3, 4, 7, 2)]
你可以解包:
>>> X,Y = zip(*sorted(zip(X,Y)))
>>> X
(1, 2, 3, 5, 6)
>>> Y
(6, 3, 4, 7, 2)
现在你有tuple
代替list
对象,但如果你真的需要,你可以将它转换回来。
正如评论中所指出的,这确实引入了对排序中第二个列表的非常轻微的依赖:考虑列表:
X = [1,1,5,7] #sorted already
Y = [2,1,4,6] #Not already sorted.
使用我上面的“食谱”,在一天结束时,你会得到:
X = (1,1,5,7)
Y = (1,2,4,6)
这可能是出乎意料的。要解决此问题,您可以将key
参数传递给sorted
:
from operator import itemgetter
X,Y = zip(*sorted(zip(X,Y),key=itemgetter(0)))
演示:
>>> X
[1, 1, 5, 7]
>>> Y
[2, 1, 4, 6]
>>> XX,YY = zip(*sorted(zip(X,Y)))
>>> XX
(1, 1, 5, 7)
>>> YY
(1, 2, 4, 6)
>>> from operator import itemgetter
>>> XX,YY = zip(*sorted(zip(X,Y),key=itemgetter(0)))
>>> XX
(1, 1, 5, 7)
>>> YY
(2, 1, 4, 6)
另一个想法:
>>> d = dict(zip(Y, X))
>>> sorted(Y, key=d.get)
[6, 3, 4, 7, 2]
您只需X
在排序时使用相应的值作为键Y
。
这是一种即使有重复项目也能保持顺序的方法:
def argsort(seq):
'''
>>> seq = [1,3,0,4,2]
>>> index = argsort(seq)
[2, 0, 4, 1, 3]
Given seq and the index, you can construct the sorted seq:
>>> sorted_seq = [seq[x] for x in index]
>>> assert sorted_seq == sorted(seq)
Given the sorted seq and the index, you can reconstruct seq:
>>> assert [sorted_seq[x] for x in argsort(index)] == seq
'''
return sorted(range(len(seq)), key=seq.__getitem__)
X = (1,1,5,7)
Y = (1,2,4,6)
index = argsort(X)
print([Y[i] for i in index])
产量
[1, 2, 4, 6]
关于速度,using_argsort
似乎比using_zip
or更快using_dict
:
def using_argsort():
index = argsort(X)
return [X[i] for i in index], [Y[i] for i in index]
def using_zip():
return zip(*sorted(zip(X,Y), key = operator.itemgetter(0)))
def using_dict():
d = dict(zip(Y,X))
return sorted(X), sorted(Y, key = d.get)
X = [5,6,2,3,1]*1000
Y = [7,2,3,4,6]*1000
In [18]: %timeit using_argsort()
1000 loops, best of 3: 1.55 ms per loop
In [19]: %timeit using_zip()
1000 loops, best of 3: 1.65 ms per loop
In [21]: %timeit using_dict()
100 loops, best of 3: 2 ms per loop
我假设 x 和 y 具有相同数量的元素。对 x 进行排序时,每次交换两个值时,例如 x.swap(i,j),也会执行 y.swap(i,j)。顺便说一句,我不知道 python 所以这不是 python 语法。