best way of combining the values of 2 different tuples - python

I want to add together the values of 2 tuples (of any size), and create an output tuple.
For example:
a = (1,4)
b = (2,3)
output: (3,7)
Is there a better way to do it than just:
output = (a[0] + b[0], a[1]+b[1])

How about using a generator expression?
output = tuple(a[i] + b[i] for i in range(len(a)))
If you don't know that the tuples are the same length, you could try using something more fancy like zip (which will stop at the length of the shorter tuple), or itertools.izip (which will allow you to control how to handle different length tuples).
tuple(x+y for (x,y) in zip(a,b))

If you want to stick with 2-tuples, what you have is fine (and probably best). You might consider using a different data structure, one where the + operator adds element-wise. For example:
complex numbers add like 2-vectors (using .real and .imag components)
numpy arrays
Write your own Point class, overriding the __add__ magic method

If you wan't to do it in a way that doesn't require you spell out all elements, go with something functional:
output = tuple(map(sum, zip(a,b)))
or, a list-comp which you, again, must supply to tuple:
output = tuple([i+j for i,j in zip(a,b)])
you could always substitute zip with zip_longest from itertools, using a fill value of 0, if the sizes might differ.

tuple(map(lambda x, y: x + y, a, b))

import operator
tuple(map(operator.add, a, b))

Related

Differentiating a tuple from a tuple of tuples

I have a tuple, and a tuple of tuples.
import numpy as np
a = ("Control", "Group1")
b = (("Control", "Group1"), ("Control", "Group1", "Group2))
How can I tell that a is fundamentally different from b? Both
print(len(a))
print(np.shape(a))
print(len(np.shape(a)))
and
print(len(b))
print(np.shape(b))
print(len(np.shape(b)))
produce the same output:
2
(2,)
1
Thanks in advance again!
You cannot, because they are not fundamentally different.
What should happen for the following?
c = (("Foo", "bar"), "baz")
It’s also a tuple, and it contains both "bare" values as well as another tuple.
If you need to detect tuples which only consist of tuples, use:
if all(isinstance(element, tuple) for element in a)
If you need to detect tuples which only consist of non-tuples, use:
if not any(isinstance(element, tuple) for element in a)
Both of the above are have a time complexity of O(n) (with n being the number of elements in a), which may not be desirable depending from where your data is coming. It is however unavoidable, unless you are willing to take the risk not actually having tuples of tuples.
Depending on what you’re doing with your data, you might actually want to check for a sequence of sequences. In that case, you should use the Sequence ABC (Python 2):
import collections.abc
if all(isinstance(element, collections.abc.Sequence) for element in a)
Use the equality operator, ==:
>>> a = ("Control", "Group1")
>>> b = (("Control", "Group1"), ("Control", "Group1", "Group2"))
>>> a == b
False
If you just want a vague idea of the general structure, and the string elements won't contain parentheses, you can count the parentheses:
>>> str(a).count('(')
1
>>> str(b).count('(')
3

"Map" a nested list in Python [duplicate]

This question already has answers here:
How can I use list comprehensions to process a nested list?
(13 answers)
Closed 8 months ago.
In Python, I am trying to apply an operator to a two layer nested array. For example,
a = [['2.3','.2'],['-6.3','0.9']]
for j in range(2)
for i in range(2)
a[i][j] = float(a[i][j])
How can I do this without the loops? I am hoping for something akin to a= map(float,a). Of course the last script does not work for a nested list. A one line list comprehension may be acceptable too.
One-liner with mix of map and listcomp:
a = [map(float, suba) for suba in a] # Only works on Py2
Or variants:
# Both of the below work on Py2 and Py3
a = [list(map(float, suba)) for suba in a]
a = [[float(x) for x in suba] for suba in a]
Choose based on your personal preference and target Python version. For large nested lists on CPython 2, the first variant is probably the fastest (if the inner lists are huge, it avoids lookup overhead to get the float constructor and byte code execution for the inner lists), and the list wrapped equivalent might eventually win on CPython 3; for small nested lists on all versions, the nested list comprehensions is usually going to be the fastest.
With list comprehension:
a = [[float(j) for j in i] for i in a]
The first argument requires a function, and as such, you can utilize the lambda operator to map float to the sub-lists. This is an example:
a = map(lambda b : map(float, b), a)
Under the hood, map is a loop too. You should just use a list comprehension, however there is a nice way to do it with Python2 - you just need a partial function
>>> a = [['2.3','.2'],['-6.3','0.9']]
>>> from functools import partial
>>> map(partial(map, float), a)
[[2.3, 0.2], [-6.3, 0.9]]
I don't think there is a nice way to convert this to Python3 though
>>> list(map(list, map(partial(map, float), a))) #YUKKK!
[[2.3, 0.2], [-6.3, 0.9]]

Python: get parent list

Is there a way to get the parent list, if some element is given? For instance, I have two lists a and b, and I want
def func(a,b):
mx = max(a[0], b[0]);
mn = min(a[0], b[0]);
return (the list that corresponds to (mx, mn) in the order)
Edit: for the above example, a simple if else is enough; but I wonder how to do it if I am dealing with many lists, and want to return, say, the name of the lists in the order of comparison? One solution I can come up with is use numpy sorting, which uses n log(n) sorting algorithms. Is there faster way?
Edit: Probably using numpy sorting is the way.
No, it is not possible. But you can get the list corresponding the maximum of the first elements, with conditional expression, like this
a, b = [1, 2], [2, 1]
c = a if a[0] > b[0] else b
print c
# [2, 1]
So, your function can be written as
def func(a,b):
return a if a[0] > b[0] else b
Since you mentioned numpy, simply use argmin and argmax.
def func(a,b):
lists = (a, b)
vals = np.array([a[0], b[0]])
return ( lists[np.argmax(vals)], lists[np.argmin(vals)] )
This can easily be generalised to more than two lists, and if all lists are of the same length, func can elegantly work on a 2dim array, e.g.:
def func(arr):
return ( arr[np.argmax(arr[:,0])], arr[np.argmin(arr[:,0])] )
You can use the key parameter of the max function.
import operator
def func(a,b):
return max(a, b, key=operator.itemgetter(0))

iterate over list of tuples in two notations

I'm iterating over a list of tuples, and was just wondering if there is a smaller notation to do the following:
for tuple in list:
(a,b,c,d,e) = tuple
or the equivalent
for (a,b,c,d,e) in list:
tuple = (a,b,c,d,e)
Both of these snippits allow me to access the tuple per item as well as as a whole. But is there a notation that somehow combines the two lines into the for-statement? It seems like such a Pythonesque feature that I figured it might exist in some shape or form.
The pythonic way is the first option you menioned:
for tup in list:
a,b,c,d,e = tup
This might be a hack that you could use. There might be a better way, but that's why it's a hack. Your examples are all fine and that's how I would certainly do it.
>>> list1 = [(1, 2, 3, 4, 5)]
>>> for (a, b, c, d, e), tup in zip(list1, list1):
print a, b, c, d, e
print tup
1 2 3 4 5
(1, 2, 3, 4, 5)
Also, please don't use tuple as a variable name.
There isn't anything really built into Python that lets you do this, because the vast majority of the time, you only need to access the tuple one way or the other: either as a tuple or as separate elements. In any case, something like
for t in the_list:
a,b,c,d,e = t
seems pretty clean, and I can't imagine there'd be any good reason to want it more condensed than that. That's what I do on the rare occasions that I need this sort of access.
If you just need to get at one or two elements of the tuple, say perhaps c and e only, and you don't need to use them repeatedly, you can access them as t[2] and t[4]. That reduces the number of variables in your code, which might make it a bit more readable.

taking intersection of N-many lists in python

what's the easiest way to take the intersection of N-many lists in python?
if I have two lists a and b, I know I can do:
a = set(a)
b = set(b)
intersect = a.intersection(b)
but I want to do something like a & b & c & d & ... for an arbitrary set of lists (ideally without converting to a set first, but if that's the easiest / most efficient way, I can deal with that.)
I.e. I want to write a function intersect(*args) that will do it for arbitrarily many sets efficiently. What's the easiest way to do that?
EDIT: My own solution is reduce(set.intersection, [a,b,c]) -- is that good?
thanks.
This works for 1 or more lists. The 0 lists case is not so easy, because it would have to return a set that contains all possible values.
def intersection(first, *others):
return set(first).intersection(*others)
This works with 1 or more lists and does not use multiple parameters:
>>> def intersection(*listas):
... return set(listas[0]).intersection(*listas[1:])
...
>>> intersection([1,2,3,4],[4,5,6],[2,4,5],[1,4,8])
set([4])
>>> intersection([1,2,3,4])
set([1, 2, 3, 4])
>>>
Not sure this is better than other answers, anyway.
lists = [[5,4,3], [4,2], [6,2,3,4]]
try:
# the following line makes one intersection too much, but I don't think
# this hurts performance noticably.
intersected = set(lists[0]).intersection(*lists)
except ValueError:
# no lists[0]
intersected = set()
print intersected # set([4])
Sets can be intersected with any iterable, there's no need to convert it into a set first.

Categories