Kalle Halvarsson
Kalle Halvarsson

Reputation: 1268

Python: Building a tuple consisting of min values from list of tuples

I'm absolutely sure this question must have been asked multiple times before, but for the life of me i couldn't find a thread answering this question:

I am making a model exporter where i want to calculate the minimum and maximum bounds of each object, by going through a list of vertices and picking the lowest and highest x, y, and z values into their own min/max tuple on the same form. The way i do this right now is like this:

x = max(vertices,key=itemgetter(0))[0]
y = max(vertices,key=itemgetter(1))[1]
z = max(vertices,key=itemgetter(2))[2]
extents_max = (x, y, z)
x = min(vertices,key=itemgetter(0))[0]
y = min(vertices,key=itemgetter(1))[1]
z = min(vertices,key=itemgetter(2))[2]
extents_min = (x, y, z)

And this works, but is there a more elegant, one-liner way of doing this in python?

Upvotes: 1

Views: 142

Answers (3)

Patrick Artner
Patrick Artner

Reputation: 51683

Demodata:

verts =  [(-94, -24, -87), (90, 27, -56), (-22, -59, -44), (50, -70, 52),
          (-31, 37, -24), (-73, 53, 66), (-47, -28, 99), (-3, -42, -66), 
          (2, 85, 58), (79, -86, 39)]

Find min/max:

z = [(min(l),max(l)) for l in zip(*verts)]  # [(min,max) for each 
                                                  #  (x0,..,xn),(y0,..,yn),(z0,..,zn) ]

extends_min, extends_max = zip(*z)

print(extends_min, extends_max)

Output:

(-94, -86, -87) (90, 85, 99)

Upvotes: 0

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477190

You can calculate these with sequence unpacking:

mins, maxs = zip(*[(min(map(itemgetter(i), vertices)),
                    max(map(itemgetter(i), vertices)))
                   for i in range(3)])

For example:

>>> vertices = [(1,4,2), (1,3,0), (4,2,5)]
>>> mins, maxs = zip(*[(min(map(itemgetter(i), vertices)),
...                     max(map(itemgetter(i), vertices)))
...                    for i in range(3)])
>>> mins
(1, 2, 0)
>>> maxs
(4, 4, 5)

Upvotes: 1

llllllllll
llllllllll

Reputation: 16424

Just remove your repeated 0, 1, 2, it's a one-liner:

extents_max = [max(vertices,key=itemgetter(i))[i] for i in range(3)]

If you need it to remain a tuple as you have shown in your example:

extents_max = tuple(max(vertices,key=itemgetter(i))[i] for i in range(3))

Upvotes: 2

Related Questions