假设我有两个列表:
list1 = [3, 2, 4, 1, 1]
list2 = ['three', 'two', 'four', 'one', 'one2']如果我运行list1.sort(),它会将它排序到[1,1,2,3,4],但是有没有办法让list2也同步(所以我可以说item 4属于'three')?因此,预期输出将是:
list1 = [1, 1, 2, 3, 4]
list2 = ['one', 'one2', 'two', 'three', 'four']我的问题是,我有一个非常复杂的程序,可以很好地处理列表,但我需要开始引用一些数据。我知道这对字典来说是一个完美的情况,但我正在努力避免在处理过程中使用字典,因为我确实需要对键值进行排序(如果我必须使用字典,我知道如何使用它们)。
基本上,这个程序的本质是,数据以随机的顺序出现(就像上面的),我需要对它进行排序,处理它,然后发送结果(顺序并不重要,但用户需要知道哪个结果属于哪个键)。我想过先把它放在字典里,然后再对列表进行排序,但如果不能保持顺序,我将无法区分具有相同值的条目(这可能会影响向用户传达结果)。因此,理想情况下,一旦我得到列表,我宁愿找出一种方法将这两个列表排序在一起。这个是可能的吗?
发布于 2012-03-19 10:45:12
解决这个问题的一个经典方法是使用“装饰,排序,取消装饰”的习惯用法,使用python内置的zip函数尤其简单:
>>> list1 = [3,2,4,1, 1]
>>> list2 = ['three', 'two', 'four', 'one', 'one2']
>>> list1, list2 = zip(*sorted(zip(list1, list2)))
>>> list1
(1, 1, 2, 3, 4)
>>> list2
('one', 'one2', 'two', 'three', 'four')当然,这些不再是列表,但这很容易补救,如果重要的话:
>>> list1, list2 = (list(t) for t in zip(*sorted(zip(list1, list2))))
>>> list1
[1, 1, 2, 3, 4]
>>> list2
['one', 'one2', 'two', 'three', 'four']值得注意的是,上面的版本可能会牺牲速度以换取简洁;就地版本,占3行,在我的机器上处理小列表的速度要快一点:
>>> %timeit zip(*sorted(zip(list1, list2)))
100000 loops, best of 3: 3.3 us per loop
>>> %timeit tups = zip(list1, list2); tups.sort(); zip(*tups)
100000 loops, best of 3: 2.84 us per loop另一方面,对于更大的列表,单行版本可能更快:
>>> %timeit zip(*sorted(zip(list1, list2)))
100 loops, best of 3: 8.09 ms per loop
>>> %timeit tups = zip(list1, list2); tups.sort(); zip(*tups)
100 loops, best of 3: 8.51 ms per loop正如Quantum7指出的那样,JSF's suggestion更快一些,但它可能只会更快一点,因为它使用very same DSU idiom internally进行所有基于键的排序。它只是发生在离裸机更近一点的地方。(这显示了zip例程的优化程度有多好!)
我认为zip-based方法更灵活,可读性更好,所以我更喜欢它。
发布于 2012-03-19 10:48:50
您可以使用值作为键对索引进行排序:
indexes = range(len(list1))
indexes.sort(key=list1.__getitem__)要获取给定排序索引的排序列表,请执行以下操作:
sorted_list1 = map(list1.__getitem__, indexes)
sorted_list2 = map(list2.__getitem__, indexes)在您的示例中,您不应该使用list1、list2,而应该使用单个配对列表:
data = [(3, 'three'), (2, 'two'), (4, 'four'), (1, 'one'), (1, 'one2')]它很容易创建;在Python中很容易排序:
data.sort() # sort using a pair as a key仅按第一个值排序:
data.sort(key=lambda pair: pair[0])发布于 2013-10-10 07:04:11
我已经使用senderle给出的答案很长一段时间了,直到我发现了np.argsort。下面是它的工作原理。
# idx works on np.array and not lists.
list1 = np.array([3,2,4,1])
list2 = np.array(["three","two","four","one"])
idx = np.argsort(list1)
list1 = np.array(list1)[idx]
list2 = np.array(list2)[idx]我发现这个解决方案更直观,而且工作得很好。性能:
def sorting(l1, l2):
# l1 and l2 has to be numpy arrays
idx = np.argsort(l1)
return l1[idx], l2[idx]
# list1 and list2 are np.arrays here...
%timeit sorting(list1, list2)
100000 loops, best of 3: 3.53 us per loop
# This works best when the lists are NOT np.array
%timeit zip(*sorted(zip(list1, list2)))
100000 loops, best of 3: 2.41 us per loop
# 0.01us better for np.array (I think this is negligible)
%timeit tups = zip(list1, list2); tups.sort(); zip(*tups)
100000 loops, best for 3 loops: 1.96 us per loop尽管np.argsort不是最快的,但我发现它更容易使用。
https://stackoverflow.com/questions/9764298
复制相似问题