1

I am using Python 3.2.3, and would like to find the largest number from specific elements in a list. It is also important that I retain some knowledge of which element is the largest number, but am quite flexible on how this occurs. Let me explain...

Background

I have the following list:

the_list = ['Order', '1', '5', 'Order', '2', '18', 'Order', '3', '45', 'Order', '4', '2', 'Order', '5', '8', 'Order', '6', '2', 'Order', '7', '1', 'Order', '8', '1', 'Order', '9', '1']

Out of every three list elements, the first two are descriptive of the data -- i.e., "Order 1", "Order 2", "Order 3" as 'Order', '1', ... 'Order', '2', ... 'Order', '3', ... all the way to "Order 9". These do not change, and provide the source or name of every third list element.

The third of every three list elements is the information in question. In this example, the numbers are 5... 18... 45... 2... and so forth. It from this every third element that I would like to find the largest number. In this case, that largest number is 45. These numbers change all the time; they could be any whole number from 0 through 100 [inclusive].

What I Have Tried So Far

I have tried using Python's max() function in two ways. First, simply...

max(the_list)

... which provides "Order" as the maximum value. A bummer on my goal.

So I decided to try making a new list, made only of every third element of the original list. Like so...

foo = (the_line[2], the_line[5], the_line[8], the_line[11], the_line[14], the_best_line[17], the_best_line[20], the_best_line[23], the_best_line[26])

max(foo)

... which provides "8" as the largest number, the 15th list element and the 5th third list element. It's a number, but isn't the highest number of 45 [in this example].

I have also dabbled in making a series of if-else statements, but was both unsuccessful and in the mind-set that there must be a more pythonic//elegant way. I admit that I may have quit too early on this route, and//or that I am in the wrong mind-set.

ThinkingStiff
  • 64,767
  • 30
  • 146
  • 239
MilesNielsen
  • 247
  • 1
  • 4
  • 9

4 Answers4

8

Something like this should work:

>>> the_list = ['Order', '1', '5', 'Order', '2', '18', 'Order', '3', '45', 'Order', '4', '2', 'Order', '5', '8', 'Order', '6', '2', 'Order', '7', '1', 'Order', '8', '1', 'Order', '9', '1']
>>> the_list[::3]
['Order', 'Order', 'Order', 'Order', 'Order', 'Order', 'Order', 'Order', 'Order']
>>> the_list[2::3]
['5', '18', '45', '2', '8', '2', '1', '1', '1']
>>> max(int(num) for num in the_list[2::3])
45

Where I've used Python's slice notation to get every third (that's the 3) element starting at element #2 (that's the 2), using the_list[2::3].

By itself that's not enough, though, because the entries of the_list are strings and they're sorted lexicographically, not numerically. That's why I had to call int(num) on each of the terms and pass max a generator expression, here in the form '(something for elem in someseq)'.

You also say that it's important that you keep track of which element is the largest, by which I assume you mean you want the index. Given the maximum value it's easy to find which elements have it (in the general case it might not be unique, after all) using another search for elements that match it which is probably the simplest. Alternatively, you could encode the index itself into the max call:

>>> max((int(num), i) for i, num in enumerate(the_list[2::3]))
(45, 2)

which gives the max and the group-of-three index, and works because tuples are sorted by the first element, then the second, etc. This approach doesn't handle non-unique maxima as well.

To be honest, though, I'd probably start by reshaping the data kind of like @astynax did-- it doesn't feel like this list should be flat.

Community
  • 1
  • 1
DSM
  • 342,061
  • 65
  • 592
  • 494
  • Thank you very much! I likely should try reshaping the data, but for now the last but which provides (45, 2) will be very nice. – MilesNielsen Jun 24 '12 at 23:26
5
>>> the_list = ['Order', '1', '5', 'Order', '2', '18', 'Order', '3', '45', 'Order', '4', '2', 'Order', '5', '8', 'Order', '6', '2', 'Order', '7', '1', 'Order', '8', '1', 'Order', '9', '1']
>>> items = zip(*[iter(the_list)] * 3)
>>> items
[('Order', '1', '5'), ('Order', '2', '18'), ('Order', '3', '45'), ('Order', '4', '2'),('Order', '5', '8'), ('Order', '6', '2'), ('Order', '7', '1'), ('Order', '8', '1'), ('Order', '9', '1')]    
>>> max(items, key=lambda x: int(x[2]))
('Order', '3', '45')
  • I found this to work for me as well, and will include this method in my further script development. Very neat solution, thank you :) – MilesNielsen Jun 24 '12 at 23:27
3
   >>> the_list = ['Order', '1', '5', 'Order', '2', '18', 'Order', '3', '45', 'Order', '4', '2', 'Order', '5', '8', 'Order', '6', '2', 'Order', '7', '1', 'Order', '8', '1', 'Order', '9', '1']
   >>> max(map(int,the_list[2::3]))
    45

here 3 in [2::3] represent step, i.e after '5' it jumps to '18' and then to '45', and so on, taking a jump of 3 every time. The default value of step is 1 if not provided. So,

>>> the_list[2::3]
['5', '18', '45', '2', '8', '2', '1', '1', '1']

map() is a function which applies a particular function to every object of an iterable, which in this case is the_list[2::3] and the function applied is int. map() returns a list in python 2.x and map object in python 3.x.

Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
0

You can try something like

my_max = max( [the_list[i] for i in range(len(the_list)) if (i+1)%3==0 ] )
GL770
  • 2,910
  • 1
  • 14
  • 9
  • For me this returns '8', which is not the answer we are looking for. Additionally, there's no need to create a list via those square brackets: you can just pass the generator expression straight to max. – Nolen Royalty Jun 24 '12 at 18:06