2015-05-24 4 views
3
l = [0, 1, 3, 2] 

l2 = ['foo', 3, 'bar', 10] 

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

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

ответ

6

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

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

так, когда вы говорите 'sorted' в список кортежей, он будет сортировать список на основе первых значений каждого кортежа? – Ogen

+1

Кортежи сравниваются как последовательность, что означает сначала сравнивать первый элемент, если он равен, сравнивать второй и т. Д. См. Http://stackoverflow.com/questions/5292303/python-tuple-comparison. –

+2

Обратите внимание, что если два элемента из 'l' равны, это будет сравнивать элементы' l2', чтобы определить порядок. Это может быть нежелательным, особенно на Python 3, где попытка сравнения семантически неупорядоченных типов создаст исключение. Если это проблема, вы можете использовать '[z для x, y, z в отсортированном (zip (l, range (len (l)), l2)]', чтобы избежать сравнения элементов 'l2'. – user2357112

4

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'] 
Смежные вопросы