5

I have a list of lists

list_of_lists = [['a',1,19,5]['b',2,4,6],['c',22,5,9],['d',12,19,20]]

and I'd like to get the top x lists with the highest values so top 3 max(list_of_lists) would return

[['c',22, 5,9],['d',12,19,20],['a',1,19,5]]

or if I'm looping through list_of_lists I could append each of the lists with the top x max values to another list of lists, based upon the index of the selected lists.

Here's the code I'm working with but it's flawed as I think I need to delete the selected answer at the end of each loop so it doesn't appear in the next loop and it only looks at column 4 (x[3])

for y in case_list:
    last_indices = [x[3] for x in case_list]
    print("max of cases is: ",max(last_indices))

And the output of that is currently:

max of cases is:  22
max of cases is:  22
max of cases is:  22

This answer gives the top max list but I would like to have the flexibility to return the top x rather than just one.

This answer gives the top x max values in a single list.

benvc
  • 14,448
  • 4
  • 33
  • 54
Jazzmine
  • 1,837
  • 8
  • 36
  • 54
  • 1
    Are the `a`, `b`, `c`, and `d` items in your list of lists supposed to be strings (and you are missing the quote marks) or are they references to previously defined variables? – benvc Oct 23 '18 at 23:45
  • 1
    the first is a string and the rest are int values. Thanks – Jazzmine Oct 23 '18 at 23:52
  • 1
    you can use numpy and do an argsort. Then use unravel_index to get 2d indices, keep the first x rows in first column, and what you get is the indices for top x max – ZisIsNotZis Oct 24 '18 at 00:00

1 Answers1

4

If your nested lists always have only one string at the first index (as in your example), then you sort your list of lists by max value using max() on a slice of each nested list excluding the first item. Then, just slice the final output based on the number of "top" results you want. Following is an example of getting the "top" 3 lists with max values.

list_of_lists = [['a',1,19,5],['b',2,4,6],['c',22,5,9],['d',12,19,20]]

# sort nested lists descending based on max value contained
sorted_list = sorted(list_of_lists, key=lambda x: max(x[1:]), reverse=True)

# slice first 3 lists (to get the "top" 3 max values)
sliced_list = sorted_list[:3]

print(sliced_list)  
# OUTPUT
# [['c', 22, 5, 9], ['d', 12, 19, 20], ['a', 1, 19, 5]]

You could turn it into a simple function to get the top "x" number of nested lists (the loop after the function is purely to print something similar to your example).

def max_lists(data, num):
    results = sorted(data, key=lambda x: max(x[1:]), reverse=True)
    return results[:num]

list_of_lists = [['a',1,19,5],['b',2,4,6],['c',22,5,9],['d',12,19,20]]

top_three = max_lists(list_of_lists, 3)

print(top_three)                     
for x in top_three:
    print(f'max value: {max(x[1:])} list: {x}')

# OUTPUT
# [['c', 22, 5, 9], ['d', 12, 19, 20], ['a', 1, 19, 5]]
# max value: 22 list: ['c', 22, 5, 9]
# max value: 20 list: ['d', 12, 19, 20]
# max value: 19 list: ['a', 1, 19, 5]
benvc
  • 14,448
  • 4
  • 33
  • 54
  • Thank you very much! What would be the best place to copy the selected ones to another list of lists? In the max_lists function or copy top_three to the other list of lists? Could you share how I would do this. Again, thanks. – Jazzmine Oct 24 '18 at 00:45
  • Also, could you explain how it spans checking all the columns? That's the only part I don't get of the code. – Jazzmine Oct 24 '18 at 00:48
  • @Jazzmine after reading your comments again, it seems that I may not be following your question after all. Are you trying to compare each nested list and select one or more that contain the highest value at any index? Or are you trying to compare each nested list and select one with the highest value at a particular index (i.e. the list with the highest value at index 1, or "column" 1)? – benvc Oct 24 '18 at 01:40
  • 2
    Hi benvc - it is the former, I am trying to use the highest value among all three int columns for each list and finding the top three lists within the list of lists with at least one value among the top x, without using a row more than once. Does that help? I think that is what you provided because your code correctly selects the list with 22, then the list with 20, then the list with 19, not considering the list with 19 and 20 again as it was already used. Does that help clarify what I'm seeking? – Jazzmine Oct 24 '18 at 01:52
  • @Jazzmine - yes, in that case we are on track. Edited answer with a simplification to return just a list of lists since that sounds like what you really want (rather than the tuples with a list and the max value). You can see in the print loop how you can easily get the max value for display if needed. – benvc Oct 24 '18 at 01:58
  • Thank you again, I appreciate your help. Could you explain this: max(x[1:]) ? Is it saying find the max of the current row's elements and it does that in a for loop type fashion on the lists in data via the lambda? – Jazzmine Oct 24 '18 at 02:05
  • @Jazzmine `max()` takes a list as a parameter and finds the highest value in the list. Since your lists contain a string value at index 0, I am passing a slice of the list starting at index 1, `[1:]`, to the `max()` function in order to find the highest value in the list excluding the string value. The `sorted()` function is the one that is iterating through the list of lists and applying the `max()` function to each nested list. Make sense? – benvc Oct 24 '18 at 02:08
  • Totally. Thanks – Jazzmine Oct 24 '18 at 02:12