Mimic array swaps from sort

l = [0, 1, 3, 2]

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

      

If I say sorted(l)

, I get it [0, 1, 2, 3]

. It will replace the last two items.

How can I apply the same pivot swaps to l2

? I want it to l2

be ['foo', 3, 10, 'bar']

.

+3


source to share


2 answers


You can use zip

, unpack the tuple and understand the list to achieve results:



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

      

+6


source


TL; DR

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

      


Explanation

  • zip

    both lists together

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

  • then sort them, (since we will get tuples from zip

    , the first elements of the tuples will be compared first, and only if they are the same, the second element will be compared. Thus, the sorting effectively happens from the value l

    )

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

  • and then unzip them,

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

    you can actually unzip l

    and l2

    for example

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




An alternative approach

You can actually sort the values ​​along with the current index and then you can restore the values ​​like this

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

      

+4


source







All Articles