Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sorting list of lists and getting indices in unsorted list

These are the logical steps that I need to perform on my list of lists

a = [[5,2],[7,4],[0,3]]
  1. sort the list of lists in such a way that the output looks something like

    7,5,4,3,2,0
    
  2. take the coordinates of the sorted elements in the original list, which in this case should produce as output

    (1,0)
    (0,0)
    (1,1)
    (2,1)
    (0,1)
    (2,0)
    

I tried using of sort, sorted and argwhere in different ways but I am not getting sensible results, I guess first of all because sort and sorted can sort a list following only one axis at a time

like image 571
johnhenry Avatar asked Nov 01 '16 10:11

johnhenry


People also ask

How do I find the indices of a sorted list?

Use enumerate() to get the indices of a sorted array Call sorted(iterable, key: NoneType=None) with the enumerate object as iterable and operator. itemgetter(1) as key to construct a sorted list of index-element tuples.

What is the difference between list sort () and sorted list?

The primary difference between the two is that list. sort() will sort the list in-place, mutating its indexes and returning None , whereas sorted() will return a new sorted list leaving the original list unchanged.

How do you sort a list of lists by an index of each inner list in Python?

To sort a list of lists using the element at index n of the inner list, We will pass the inner lists as the input argument to the lambda function. We will use the element at index n of the inner list as the expression in the lambda function.


3 Answers

This code will work for a list of lists. The internal lists don't have to be the same length.

At each level we iterate over a list using enumerate to get the list item and its index. At the top level, each item is another list, and the inner loop iterates over each of those lists to get their indices and values, storing the indices (as a tuple) in a tuple that also contains the value. We then sort the resulting list of tuples (b) on the values, and then split it using zip into a tuple of all the indices and a tuple of the values.

from operator import itemgetter

a = [[5, 2], [7, 4], [0, 3]]

b = [((i, j), v) for i, t in enumerate(a) for j, v in enumerate(t)]
b.sort(key=itemgetter(-1), reverse=True)
print(b)
coords, vals = zip(*b)
print(vals)
print(coords)

output

[((1, 0), 7), ((0, 0), 5), ((1, 1), 4), ((2, 1), 3), ((0, 1), 2), ((2, 0), 0)]
(7, 5, 4, 3, 2, 0)
((1, 0), (0, 0), (1, 1), (2, 1), (0, 1), (2, 0))
like image 137
PM 2Ring Avatar answered Oct 29 '22 01:10

PM 2Ring


Create a dictionary with the keys as the actual coordinates and the values as the numbers themselves, like this

>>> a = [[5, 2], [7, 4], [0, 3]]
>>> positions = {
...     (idx1, idx2): col
...     for idx1, row in enumerate(a)
...     for idx2, col in enumerate(row)
... }
>>> positions
{(0, 1): 2, (2, 0): 0, (0, 0): 5, (1, 0): 7, (1, 1): 4, (2, 1): 3}

Now, sort the keys (coordinates) of positions based on their values, like this

>>> sorted(positions, key=positions.get, reverse=True)
[(1, 0), (0, 0), (1, 1), (2, 1), (0, 1), (2, 0)]
like image 45
thefourtheye Avatar answered Oct 28 '22 23:10

thefourtheye


You can use a series of list comprehensions and zip blocks, although the readability suffers:

n, idxs = zip(*sorted(zip([i for sl in a for i in sl], [(col, row) for col in range(len(a)) for row in range(len(a[col]))]), key=lambda x: x[0], reverse=True))

print n, idxs
>>> (7, 5, 4, 3, 2, 0) ((1, 0), (0, 0), (1, 1), (2, 1), (0, 1), (2, 0))

If you need a dict, just replace the zip(*..) layer with dict()

like image 25
kezzos Avatar answered Oct 28 '22 23:10

kezzos