Rolando
Rolando

Reputation: 13

Pick from n equal items, the one associated with the smallest number

I dont know how to explaind this but I'll give it a try. I have a list1 = [('Lista-A', 2000), ('Lista-X', 1000), ('Lista-Z', 5000)]) then i will have a

list2 = [['Lista-A', 2000.0],
 ['Lista-A', 1000.0],
 ['Lista-A', 666.6666666666666],
 ['Lista-A', 500.0],
 ['Lista-A', 400.0],
 ['Lista-A', 333.3333333333333],
 ['Lista-X', 1000.0],
 ['Lista-X', 500.0],
 ['Lista-X', 333.3333333333333],
 ['Lista-X', 250.0],
 ['Lista-X', 200.0],
 ['Lista-X', 166.66666666666666],
 ['Lista-Z', 5000.0],
 ['Lista-Z', 2500.0],
 ['Lista-Z', 1666.6666666666667],
 ['Lista-Z', 1250.0],
 ['Lista-Z', 1000.0],
 ['Lista-Z', 833.3333333333334]]

Now i need to pick the n biggest items from the list2 but everytime 2 or 3 or more items have the same numeric value, the function will need to go back to the first list and check which one of its items have the smallest numeric value the from the items with equal value, it'll have to pick the one that has the same "name" (Lista-A, Z or X) as the item from the first list with the smallest numeric value. I don't if its clear what i need to do. I already tried to sort the list, but then i dont know to move on.

For this case I need the 6 biggest values, so the expected result would be

 list3 = [['Lista-Z', 5000.0],
 ['Lista-Z', 2500.0],
 ['Lista-A', 2000.0],
 ['Lista-Z', 1666.6666666666667],
 ['Lista-Z', 1250.0],
 ['Lista-x', 1000.0]]

Upvotes: 1

Views: 44

Answers (2)

Rakesh
Rakesh

Reputation: 82785

If i understood correctly

list1 = [('Lista-A', 2000), ('Lista-X', 1000), ('Lista-Z', 5000)]
list1 = dict(list1)  #Converted to dict for easy lookup

list2 = [['Lista-A', 2000.0],
 ['Lista-A', 1000.0],
 ['Lista-A', 666.6666666666666],
 ['Lista-A', 500.0],
 ['Lista-A', 400.0],
 ['Lista-A', 333.3333333333333],
 ['Lista-X', 1000.0],
 ['Lista-X', 500.0],
 ['Lista-X', 333.3333333333333],
 ['Lista-X', 250.0],
 ['Lista-X', 200.0],
 ['Lista-X', 166.66666666666666],
 ['Lista-Z', 5000.0],
 ['Lista-Z', 2500.0],
 ['Lista-Z', 1666.6666666666667],
 ['Lista-Z', 1250.0],
 ['Lista-Z', 1000.0],
 ['Lista-Z', 833.3333333333334]]
list2.sort(key=lambda x: (x[1], -list1.get(x[0], x[0])), reverse=True)

print(list2[:6])

Output:

[['Lista-Z', 5000.0],
 ['Lista-Z', 2500.0],
 ['Lista-A', 2000.0],
 ['Lista-Z', 1666.6666666666667],
 ['Lista-Z', 1250.0],
 ['Lista-X', 1000.0]]

Upvotes: 1

Seb
Seb

Reputation: 4586

One way this can be done is with NumPy's lexsort. First I'd map the first column to the corresponding numerical values:

>>> tiebreakers = dict(list1)
>>> arr = np.array([(tiebreakers[a], b) for (a, b) in list2])
>>> arr
array([[2000.        , 2000.        ],
       [2000.        , 1000.        ],
       [2000.        ,  666.66666667],
       [2000.        ,  500.        ],
       [2000.        ,  400.        ],
       [2000.        ,  333.33333333],
       [1000.        , 1000.        ],
       [1000.        ,  500.        ],
       [1000.        ,  333.33333333],
       [1000.        ,  250.        ],
       [1000.        ,  200.        ],
       [1000.        ,  166.66666667],
       [5000.        , 5000.        ],
       [5000.        , 2500.        ],
       [5000.        , 1666.66666667],
       [5000.        , 1250.        ],
       [5000.        , 1000.        ],
       [5000.        ,  833.33333333]])

Then you can sort the array as required with lexsort:

>>> order = np.lexsort((arr[:, 0], -arr[:, 1])) # Sorts by column 1 desc and column 0 asc
>>> order
array([12, 13,  0, 14, 15,  6,  1, 16, 17,  2,  7,  3,  4,  8,  5,  9, 10, 11])
>>> list3 = [list2[i] for i in order]
>>> list3[:6]
[['Lista-Z', 5000.0],
 ['Lista-Z', 2500.0],
 ['Lista-A', 2000.0],
 ['Lista-Z', 1666.6666666666667],
 ['Lista-Z', 1250.0],
 ['Lista-X', 1000.0]]

Upvotes: 1

Related Questions