2

I have 2-dimensional list in which each entry has a timestamp (int) and a second value that can be an int, string or object.

I'm using the min() function to get the entry with the lowest timestamp:

a = [[2, "start C"],
     [6, 2484],
     [15, "finish C"]]

print(min(a))

Output:

[2, 'start C']

When there are identical lowest timestamps min() will compare the second column of those items.

This works only as long as the second column has comparable values:

a = [[2, "start C"],
     [2, "start B"],
     [15, "finish C"]]

print(min(a))

Output:

[2, 'start B']

If the second column contains different data types it throws an error:

a = [[2, "start C"],
     [2, 2484],
     [15, "finish C"]]

print(min(a))

Output:

TypeError: '<' not supported between instances of 'int' and 'str'

How can I let only the first column be checked for the minimum? When there are identical timestamps it should simply return the first item encountered.

2 Answers2

4

You can pass a comparison key

min(my_list, key=lambda x: x[0])

By default, python uses the first item for comparison, and in case of tie, the second one as tie-breaker (and so on), that's why you get the error.

blue_note
  • 27,712
  • 9
  • 72
  • 90
3

min accepts a key argument, which can be used to obtain the expected behaviour:

from operator import itemgetter

a = [[2, "start C"],
     [6, 2484],
     [15, "finish C"]]

min(a, key=itemgetter(0))
# [2, 'start C']

Which is equivalent to slicing the inner lists with a custom lambda function as in @blue_note's solution, but typically somewhat faster (though its mainly a habit from being more convenient when having to fetch multiple items as explained here):

min(my_list, key=lambda x: x[0])

By using itemgetter, only the first element in each inner list will be fetched for ordering purposes, and then the minimum will be computed among this subset

yatu
  • 86,083
  • 12
  • 84
  • 139
  • You should probably also mention that this is equivalent to the `lambda` counterpart, but typically significantly faster. – norok2 Sep 30 '19 at 14:22
  • The timing difference is a bit higher than what the wording of the most accepted answer from [there](https://stackoverflow.com/a/11287216/9698684) seemed to indicate. See my [benchmarks](https://stackoverflow.com/a/58171096/5218354) for some numbers for both `sorted()` and `min()`. My understanding is that with the `lambda` version there is an extra function call implicit to the `[]` operator. – norok2 Sep 30 '19 at 15:53