为了账号安全,请及时绑定邮箱和手机立即绑定

是否可以以完全相同的方式对两个列表(相互引用)进行排序?

是否可以以完全相同的方式对两个列表(相互引用)进行排序?

LEATH 2019-08-26 15:42:42
是否可以以完全相同的方式对两个列表(相互引用)进行排序?好吧,这可能不是最明智的想法,但如果可能,我有点好奇。说我有两个清单:list1 = [3,2,4,1, 1]list2 = [three, two, four, one, one2]如果我运行list1.sort(),它会对它进行排序,[1,1,2,3,4]但有没有办法让list2保持同步(所以我可以说第4项属于'3')?我的问题是我有一个非常复杂的程序,可以正常使用列表,但我需要开始引用一些数据。我知道这对于词典来说是一个完美的情况,但我正在努力避免在我的处理中使用字典,因为我确实需要对键值进行排序(如果我必须使用字典,我知道如何使用它们)。基本上这个程序的本质是,数据以随机顺序出现(如上所述),我需要对其进行排序,处理然后发送结果(顺序无关紧要,但用户需要知道哪个结果属于哪个键)。我想先将它放在字典中,然后对列表进行排序,但如果不维护订单,我就无法区分具有相同值的项目(在将结果传达给用户时可能会产生影响)。理想情况下,一旦我得到列表,我宁愿想出一种方法来将两个列表排序在一起。这可能吗?
查看完整描述

3 回答

?
翻阅古今

TA贡献1780条经验 获得超5个赞

解决这个问题的一个经典方法是使用“decorate,sort,undecorate”这个习惯用法,这个使用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的建议还是要快一点,但它可能只会更快一些,因为Python在内部对所有基于密钥的排序使用完全相同的DSU惯用法。它刚好接近裸金属。(这显示了zip例程的优化程度!)


我认为zip基于-Based的方法更灵活,更具可读性,所以我更喜欢它。


查看完整回答
反对 回复 2019-08-26
?
米琪卡哇伊

TA贡献1998条经验 获得超6个赞

您可以使用值作为键对索引进行排序:

indexes = range(len(list1))indexes.sort(key=list1.__getitem__)

获取给定排序索引的排序列表:

sorted_list1 = map(list1.__getitem__, indexes)sorted_list2 = map(list2.__getitem__, indexes)

在你的情况下,你不应该有list1list2而是一个对的列表:

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])


查看完整回答
反对 回复 2019-08-26
?
MYYA

TA贡献1868条经验 获得超4个赞

在发现之前,我已经使用了发送者给出的答案很长一段时间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不是最快的,我发现它更容易使用。


查看完整回答
反对 回复 2019-08-26
  • 3 回答
  • 0 关注
  • 606 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信