1

My list of tuples look like this:

[(0, 0), (3, 0), (3, 3), (0, 3), (0, 0), (0, 6), (3, 6), (3, 9), (0, 9), (0, 6), (6, 0), (9, 0), (9, 3), (6, 3), (6, 0), (0, 3), (3, 3), (3, 6), (0, 6), (0, 3)]

It has the format of (X, Y) where I want to get the max and min of all Xs and Ys in this list.

It should be min(X)=0, max(X)=9, min(Y)=0, max(Y)=9

However, when I do this:

min(listoftuples)[0], max(listoftuples)[0]
min(listoftuples)[1], max(listoftuples)[1]

...for the Y values, the maximum value shown is 3 which is incorrect.

Why is that?

yoyo
  • 23
  • 7
  • Applying `max` to a tuple simply returns the largest value within it. For example, `max((0,9))` is `9`. So applying `max` to a list of tuples simply returns the tuple with the largest value. – Kris Mar 12 '21 at 22:09
  • That doesn't explain the problem. The root of the problem, as explained below, is that when you sort a list of tuples, it sorts first by the first element, then by the next element. So, max(((0,1111),(9,3))) produces (0,1111) because the 0 sorts first. – Tim Roberts Mar 12 '21 at 22:12
  • @Kris *"So applying `max` to a list of tuples simply returns the tuple with the largest value."* -- No, that's incorrect. – wjandrea Mar 12 '21 at 22:13
  • @Tim `max(((0,1111),(9,3)))` -> `(9, 3)`. Maybe you meant `min`? – wjandrea Mar 12 '21 at 22:16
  • @wjandrea Apologies, that is correct. I forget about the order of the sort. – Kris Mar 13 '21 at 13:38

3 Answers3

2

for the Y values, the maximum value shown is 3

because max(listoftuples) returns the tuple (9, 3), so max(listoftuples)[0] is 9 and max(listoftuples)[1] is 3.

By default, iterables are sorted/compared based on the values of the first index, then the value of the second index, and so on.

If you want to find the tuple with the maximum value in the second index, you need to use key function:

from operator import itemgetter

li = [(0, 0), (3, 0), ... ]
print(max(li, key=itemgetter(1)))
# or max(li, key=lambda t: t[1])

outputs

(3, 9)
DeepSpace
  • 78,697
  • 11
  • 109
  • 154
0

Here is a simple way to do it using list comprehensions:

min([arr[i][0] for i in range(len(arr))])
max([arr[i][0] for i in range(len(arr))])  
min([arr[i][1] for i in range(len(arr))])
max([arr[i][1] for i in range(len(arr))]) 

In this code, I have used a list comprehension to create a list of all X and all Y values and then found the min/max for each list. This produces your desired answer.

The first two lines are for the X values and the last two lines are for the Y values.

zx01p
  • 33
  • 2
  • 7
  • 3
    Or, simpler, `min(a[0] for a in arr)`, `min(a[1] for a in arr)`, etc. Virtually any time you write `range(len(xxx))`, there's a better way. – Tim Roberts Mar 12 '21 at 22:09
0

Tuples are ordered by their first value, then in case of a tie, by their second value (and so on). That means max(listoftuples) is (9, 3). See How does tuple comparison work in Python?

So to find the highest y-value, you have to look specifically at the second elements of the tuples. One way you could do that is by splitting the list into x-values and y-values, like this:

xs, ys = zip(*listoftuples)

Or if you find that confusing, you could use this instead, which is roughly equivalent:

xs, ys = ([t[i] for t in listoftuples] for i in range(2))

Then get each of their mins and maxes, like this:

x_min_max, y_min_max = [(min(L), max(L)) for L in (xs, ys)]
print(x_min_max, y_min_max)  # -> (0, 9) (0, 9)

Another way is to use NumPy to treat listoftuples as a matrix.

import numpy as np

a = np.array(listoftuples)
x_min_max, y_min_max = [(min(column), max(column)) for column in a.T]
print(x_min_max, y_min_max)  # -> (0, 9) (0, 9)

(There's probably a more idiomatic way to do this, but I'm not super familiar with NumPy.)

wjandrea
  • 28,235
  • 9
  • 60
  • 81