Adding an integer to all values in a tuple
Asked Answered
D

4

8

What is the recommended/most pythonic way of editing a tuple in code like that shown below?

tup_list = [(1, 2), (5, 0), (3, 3), (5, 4)]
max_tup = max(tup_list)
my_tup1 = (max_tup[0] + 1, max_tup[1] + 1)
my_tup2 = tuple(map(lambda x: x + 1, max_tup))
my_tup3 = max([(x+1, y+1) for (x, y) in tup_list])

Which of the three methods above is preferred, or is there a better way to do this? (Should of course return (6, 5) in this example).

There is a temptation to do something like

my_tup = max(tup_list)[:] + 1

or

my_tup = max(tup_list) + (1, 1)

however neither of these work obviously.

Defilade answered 20/7, 2016 at 12:55 Comment(2)
The first one seems like the most readable one. You should also test the speeds with the timeit module, which I presume will give close results.Cabalistic
@Cabalistic I would agree. Speed is not a concern in this case.Defilade
S
16

Just use a generator expression with tuple:

my_tup = tuple(x+1 for x in max_tup)
# or my_tup = tuple(x+1 for x in max(tup_list))
Swayne answered 20/7, 2016 at 13:7 Comment(1)
This is what I was looking for, felt like I must be missing something!Defilade
C
2
my_tup1 = (max_tup[0] + 1, max_tup[1] + 1)

Straight-forward and easy to read. The parentheses explicitly indicate that a tuple will be created and + indicates that numbers will be modified. Therefore it also seems pythonic.

my_tup2 = tuple(map(lambda x: x + 1, max_tup))

Takes a functional approach, but a tuple is abused as list and finally it is converted back to a tuple. Not straight-forward to someone that does not know how python's tuples work.

my_tup3 = max([(x+1, y+1) for (x, y) in tup_list])

Uses the invariant that the maximum remains the same if all values are incremented by 1. So you need to wrap your head around it and this code does more work than any other approach.

So I would go for the first approach.

Conchiolin answered 20/7, 2016 at 13:8 Comment(1)
”a tuple is abused as list” — No, no tuples are abused in the making of that code.Tranquilizer
G
0

I might unpack, for example if the tuples represent (x,y) pairs:

tup_list = [(1, 2), (5, 0), (3, 3), (5, 4)]
x, y = max(tup_list)
my_tup4 = (x + 1, y + 1)
Gothard answered 29/8, 2024 at 14:56 Comment(0)
L
0

If you are looking for the maximum cumulative vector, your approach is fundamentally flawed. The built-in max() python function will return the tuple with the largest first value, meaning:

max([(1, 2), (6, 0), (3, 3), (5, 4)])

Will yield:

(6, 0)

Assuming you want the largest cumulative (summed) vector, use the following:

Using numpy's built in vectorization functionality is the most scalable solution:

import numpy as np

base_arr = np.array([(1, 2), (5, 0), (3, 3), (5, 4)])
max_vec = base_arr[base_arr.sum(axis=1).argmax()]
incremented_arr = tuple(max_vec + 1)

This uses the np.ndarray's built-in functionality rooted in highly-optimized C and Fortran pre-compiled code which uses SIMD (single instruction, multiple data) instructions provided by your CPU -- see the documentation. This allows you to make simultaneously perform arithmetic on "packed" data within your CPU's SSE/AVX registers, all with a single instruction -- see the image linked for a better visualization (I am having trouble actually adding it to this post).

Numpy seems to be rather portable in this sense, using different instruction sets (intrinsics) according to a device's CPU -- which is identified via a probe at runtime import -- so you should not have a problem with this approach.

Though less efficient, you can program your own NumPy "vectorized" function using np.vectorize -- see the documentation.

Lexington answered 30/8, 2024 at 8:28 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.