# Tutorial :Apply function to one element of a list in Python

### Question:

I'm looking for a concise and functional style way to apply a function to one element of a tuple and return the new tuple, in Python.

For example, for the following input:

``inp = ("hello", "my", "friend")  ``

I would like to be able to get the following output:

``out = ("hello", "MY", "friend")  ``

I came up with two solutions which I'm not satisfied with.

One uses a higher-order function.

``def apply_at(arr, func, i):      return arr[0:i] + [func(arr[i])] + arr[i+1:]    apply_at(inp, lambda x: x.upper(), 1)  ``

One uses list comprehensions (this one assumes the length of the tuple is known).

``[(a,b.upper(),c) for a,b,c in [inp]][0]  ``

Is there a better way? Thanks!

### Solution:1

I commented in support of your first snippet, but here are a couple other ways for the record:

``(lambda (a,b,c): [a,b.upper(),c])(inp)  ``

(Won't work in Python 3.x.) And:

``[inp[0], inp[1].upper(), inp[1]]  ``

### Solution:2

Here is a version that works on any iterable and returns a generator:

``>>> inp = ("hello", "my", "friend")  >>> def apply_nth(fn, n, iterable):  ...    return (fn(x) if i==n else x for (i,x) in enumerate(iterable))  ...   >>> tuple(apply_nth(str.upper, 1, inp))  ('hello', 'MY', 'friend')  ``

You can extend this so that instead of one position you can give it a list of positions:

``>>> def apply_at(fn, pos_lst, iterable):  ...    pos_lst = set(pos_lst)  ...    return (fn(x) if i in pos_lst else x for (i,x) in enumerate(iterable))  ...   >>> ''.join(apply_at(str.upper, [2,4,6,8], "abcdefghijklmno"))  'abCdEfGhIjklmno'  ``

### Solution:3

``>>> inp = "hello", "my", "friend"  >>> index = 1  >>> inp[:index] + ( str.upper(inp[index]),) + inp[index + 1:]  ('hello', 'MY', 'friend')  ``

Seems simple, the only thing you may need to know is that to make a single element tuple, do (elt,)

### Solution:4

Maybe some' like this?

``>>>inp = ("hello", "my", "friend")  >>>out =  tuple([i == 1 and x.upper() or x for (x,i) in zip(t,range(len(t)))])    >>> out  ('hello', 'MY', 'friend')  ``

Note: rather than `(x,i) in zip(t, range(len(t)))` I should have thought of using the enumerate function : `(i,x) in enumerate(t)`

Making it a bit more general:
Rather than hard-coding the 1, we can place it in a variable.
Also, by using a tuple for that purpose, we can apply the function to elements at multiple indexes.

``>>>inp = ("hello", "my", "friend")  >>>ix  = (0,2)  >>>out =  tuple([i in ix and x.upper() or x for (i, x) in enumerate(t)])    >>> out  ('HELLO', 'my', 'FRIEND')  ``

Also, we can "replace" the zip()/enumerate() by map(), in something like

``out = tuple(map(lambda x,i : i == 1 and x.upper() or x, inp, range(len(inp)) ) )  ``

Could be something as simple as:

``>>> f = str.upper  # or whatever function taking a single argument  >>> out = tuple(map(lambda x,i : i == 1 and f(x) or x, inp, range(len(inp)) ) )  ``

Since we're talking about applying any function, we should mention the small caveat with the `condition and if_true or if_false` construct which is not exactly a substitute for the if/else ternary operator found in other languages. The limitation is that the function cannot return a value which is equivalent to False (None, 0, 0.0, '' for example). A suggestion to avoid this problem, is, with Python 2.5 and up, to use the true if-else ternary operator, as shown in Dave Kirby's answer (note the `when_true if condition else when_false` syntax of this operator)

### Solution:5

I don't understand if you want to apply a certain function to every element in the tuple that passes some test, or if you would like it to apply the function to any element present at a certain index of the tuple. So I have coded both algorithms:

This is the algorithm (coded in Python) that I would use to solve this problem in a functional language like scheme:

This function will identify the element identifiable by `id` and apply `func` to it and return a list with that element changed to the output of `func`. It will do this for every element identifiable as `id`:

``def doSomethingTo(tup, id):      return tuple(doSomethingToHelper(list(tup), id))    def doSomethingToHelper(L, id):      if len(L) == 0:          return L      elif L[0] == id:          return [func(L[0])] + doSomethingToHelper(L[1:], id)      else:          return [L[0]] + doSomethingToHelper(L[1:], id)  ``

This algorithm will find the element at the index of the tuple and apply `func` to it, and stick it back into its original index in the tuple

``def doSomethingAt(tup, i):       return tuple(doSomethingAtHelper(list(tup), i, 0))    def doSomethingAtHelper(L, index, i):  if len(L) == 0:           return L  elif i == index:           return [func(L[0])] + L[1:]  else:           return [L[0]] + doSomethingAtHelper(L[1:], index, i+1)  ``

### Solution:6

i also like the answer that Dave Kirby gave. however, as a public service announcement, i'd like to say that this is not a typical use case for tuples -- these are data structures that originated in Python as a means to move data (parameters, arguments) to and from functions... they were not meant for the programmer to use as general array-like data structures in applications -- this is why lists exist. naturally, if you're needing the read-only/immutable feature of tuples, that is a fair argument, but given the OP question, this should've been done with lists instead -- note how there is extra code to either pull the tuple apart and put the resulting one together and/or the need to temporarily convert to a list and back.

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »