Мимируйте свопы массива из сортировки

l = [0, 1, 3, 2] l2 = ['foo', 3, 'bar', 10] 

Если я скажу, что sorted(l) , я получу [0, 1, 2, 3] . Он заменит последние два элемента.

Как я могу применить одни и те же сводные свопы к l2 ? Т.е., я хочу, чтобы l2 был ['foo', 3, 10, 'bar'] .

Вы можете использовать zip , unpack кортеж и понимание списка для достижения результатов:

 [y for x, y in sorted(zip(l, l2))] 

TL; DR

 >>> l, l2 = zip(*sorted(zip(l, l2))) >>> list(l) [0, 1, 2, 3] >>> list(l2) ['foo', 3, 10, 'bar'] 

объяснение

  1. zip оба списка вместе

     >>> list(zip(l, l2)) [(0, 'foo'), (1, 3), (2, 10), (3, 'bar')] 
  2. затем сортируйте их (так как мы получим кортежи из zip , первые элементы кортежей будут сначала сравниваться, и только если они будут одинаковыми, то второй элемент будет сравниваться. Таким образом, сортировка эффективно происходит со значениями l )

     >>> sorted(zip(l, l2)) [(0, 'foo'), (1, 3), (2, 10), (3, 'bar')] 
  3. и затем разархивируйте их,

     >>> list(zip(*sorted(zip(l, l2)))) [(0, 1, 2, 3), ('foo', 3, 10, 'bar')] 

    вы можете на самом деле разархивировать l и l2 , как это

     >>> l, l2 = zip(*sorted(zip(l, l2))) >>> l, l2 ((0, 1, 2, 3), ('foo', 3, 10, 'bar')) >>> list(l) [0, 1, 2, 3] >>> list(l2) ['foo', 3, 10, 'bar'] 

Альтернативный подход

Вы можете сортировать значения вместе с текущим индексом, а затем вы можете восстановить значения, подобные этому

 >>> l = [0, 1, 3, 2] >>> l2 = ['foo', 3, 'bar', 10] >>> l_s = sorted((value, idx) for idx, value in enumerate(l)) >>> l_s [(0, 0), (1, 1), (2, 3), (3, 2)] >>> l = [value for value, idx in l_s] >>> l [0, 1, 2, 3] >>> l2 = [l2[idx] for value, idx in l_s] >>> l2 ['foo', 3, 10, 'bar']