How flatten a list of lists one step - python

I have a list of lists of tuples
A= [ [(1,2,3),(4,5,6)], [(7,8,9),(8,7,6),(5,4,3)],[(2,1,0),(1,3,5)] ]
The outer list can have any number of inner lists, the inner lists can have any number of tuples, a tuple always has 3 integers.
I want to generate all combination of tuples, one from each list:
[(1,2,3),(7,8,9),(2,1,0)]
[(1,2,3),(7,8,9),(1,3,5)]
[(1,2,3),(8,7,6),(2,1,0)]
...
[(4,5,6),(5,4,3),(1,3,5)]
A simple way to do it is to use a function similar to itertools.poduct()
but it must be called like this
itertools.product([(1,2,3),(4,5,6)], [(7,8,9),(8,7,6),(5,4,3)],[(2,1,0),(1,3,5)])
i.e the outer list is removed. And I don't know how to do that. Is there a better way to generate all combinations of tuples?

itertools.product(*A)
For more details check the python tutorial

This works for your example, if there is only one level of nested lists (no lists of lists of lists):
itertools.product(*A)

you can probably call itertools.product like so:
itertools.product(*A) # where A is your list of lists of tuples
This way it expands your list's elements into arguments for the function you are calling.

Late to the party but ...
I'm new to python and come from a lisp background. This is what I came up with (check out the var names for lulz):
def flatten(lst):
if lst:
car,*cdr=lst
if isinstance(car,(list)):
if cdr: return flatten(car) + flatten(cdr)
return flatten(car)
if cdr: return [car] + flatten(cdr)
return [car]
Seems to work. Test:
A = [ [(1,2,3),(4,5,6)], [(7,8,9),(8,7,6),(5,4,3)],[(2,1,0),(1,3,5)] ]
flatten(A)
Result:
[(1, 2, 3), (4, 5, 6), (7, 8, 9), (8, 7, 6), (5, 4, 3), (2, 1, 0), (1, 3, 5)]
Note: the line car,*cdr=lst only works in Python 3.0

This is not exactly one step, but this would do what you want if for some reason you don't want to use the itertools solution:
def crossprod(listoflists):
if len(listoflists) == 1:
return listoflists
else:
result = []
remaining_product = prod(listoflists[1:])
for outertupe in listoflists[0]:
for innercombo in remaining_product[0]:
newcombo = [outertupe]
newcombo.append(innercombo)
result.append(newcombo)
return result

def flatten(A)
answer = []
for i in A:
if type(i) == list:
ans.extend(i)
else:
ans.append(i)
return ans

This may also be achieved using list comprehension.
In [62]: A = [ [(1,2,3),(4,5,6)], [(7,8,9),(8,7,6),(5,4,3)],[(2,1,0),(1,3,5)] ]
In [63]: improved_list = [num for elem in A for num in elem]
In [64]: improved_list
Out[64]: [(1, 2, 3), (4, 5, 6), (7, 8, 9), (8, 7, 6), (5, 4, 3), (2, 1, 0), (1, 3, 5)]

Related

Merging a tuple filled my any number of tuples in one tuple and returning that sorted

First question for this Problem is: How can I call a function with a tuple of tuples, my programm should be able to handle any number of tuples.
Second question: I found a way, but with defined tuples in my code and it works, so I need a hint how to call the function with a tuple with any number of tuples in it.
My code so far:
def merge(tuples):
tuples = ((2, 3, 4), (1, 6), (5, 1, 7))
largest_tuple = len(tuples[0])
for i in tuples:
largest_tuple = max(largest_tuple, len(i))
new_tuples = []
for i in range(largest_tuple):
tup = []
for j in tuples:
if i < len(j):
tup.append(j[i])
tup.sort()
new_tuples = new_tuples+tup
new_tuple = tuple(new_tuples)
print(new_tuple)
For example:
merge((2, 3, 4), (1, 6), (5, 1, 7))
return:
(1, 2, 5, 1, 3, 6, 4, 7)
Use A Recursive Function:
merged_tuple = [] # Here is where the solution goes
def merge(tuple_set):
for value in tuple_set: # Looping over the current tuple
if type(value) == tuple: # if that value is a tuple
merge(value) # Perform the function all over again
else:
merged_tuple.append(value) # Add the number to the solution set
return tuple(sorted(merged_tuple))

Quickest way to remove mirror opposites from a list

Say I have a list of tuples [(0, 1, 2, 3), (4, 5, 6, 7), (3, 2, 1, 0)], I would like to remove all instances where a tuple is reversed e.g. removing (3, 2, 1, 0) from the above list.
My current (rudimentary) method is:
L = list(itertools.permutations(np.arange(x), 4))
for ll in L:
if ll[::-1] in L:
L.remove(ll[::-1])
Where time taken increases exponentially with increasing x. So if x is large this takes ages! How can I speed this up?
Using set comes to mind:
L = set()
for ll in itertools.permutations(np.arange(x), 4):
if ll[::-1] not in L:
L.add(ll)
or even, for slightly better performance:
L = set()
for ll in itertools.permutations(np.arange(x), 4):
if ll not in L:
L.add(ll[::-1])
The need to keep the first looks like it forces you to iterate with a contitional.
a = [(0, 1, 2, 3), (4, 5, 6, 7), (3, 2, 1, 0)]
s = set(); a1 = []
for t in a:
if t not in s:
a1.append(t)
s.add(t[::-1])
Edit: The accepted answer addresses the example code (i.e. the itertools permutations sample). This answers the generalized question for any list (or iterable).

List to list of tuples conversion

I am brand new to Python. I can change a list to a tuple, for example
li = [1]
tuple(li)
I am trying to create a tuple that gives the item and its position, so a tuple that would come out (1, 0). I have no idea how to get started.
If you want a tuple of tuples, you can use a generator expression like this;
li = [4, 5, 6]
tuple((li[i], i) for i in range(len(li)))
Or with enumerate;
tuple((v, k) for k,v in enumerate(li))
Both will return;
((4, 0), (5, 1), (6, 2))
If you want a list of tuples, you can use a list comprehension expression like this;
[(li[i], i) for i in range(len(li))]
or with enumerate;
[(v,k) for k, v in enumerate(li)]
Both will return;
[(4, 0), (5, 1), (6, 2)]
Use enumerate which does exactly what you need, just with elements and indexes flipped:
> li = [2, 4, 6]
> [(x, i) for i, x in enumerate(li)]
[(2, 0), (4, 1), (6, 2)]
If you want a just one tuple you could do this:
li = (list[1], 1)
The brackets here are the literal syntax for tuples.
If you wanted to do it for all the elements of the list, you could use a list comprehension:
lis = [(list[i], i) for i in range(len(list))]
Which would create a list of tuples were each tuple has the element and its index.
One possible way is to use enumerate,
li = [10, 20, 30]
list(enumerate(li))
prints
[(0, 10), (1, 20), (2, 30)]
If you want the output to be in (item, position) order, you can use,
[(v, k) for k,v in enumerate(li)]
zip with range is another option:
In [4]: li = [2,4,6]
In [5]: zip(li, range(len(li)))
Out[5]: [(2, 0), (4, 1), (6, 2)]

Filtering list of tuples based on the availability of a member in a list

I want to filter a list of tuples like [(1,22,1),(5,1,8),(8,3,4),(7,5,6)] using a list like [1,7] which would eventually give me the result [(1,22,1),(5,1,8),(7,5,6)]; since (8,3,4) does not have either 1 or 7, it is eliminated.
I can write a comprehensive function for this. But I am looking for a short list comprehension if possible.
Thanks.
>>> tup_list = [(1,22,1),(5,1,8),(8,3,4),(7,5,6)]
>>> filter_list = [1,7]
>>> [tup for tup in tup_list if any(i in tup for i in filter_list)]
[(1, 22, 1), (5, 1, 8), (7, 5, 6)]
try with this one :
items = [(1,22,1),(5,1,8),(8,3,4),(7,5,6)]
result = [ item for item in items if (set([1,7]) & set(item))]
>>> [(1, 22, 1), (5, 1, 8), (7, 5, 6)]

Is there a python builtin to create tuples from multiple lists?

Is there a python builtin that does the same as tupler for a set of lists, or something similar:
def tupler(arg1, *args):
length = min([len(arg1)]+[len(x) for x in args])
out = []
for i in range(length):
out.append(tuple([x[i] for x in [arg1]+args]))
return out
so, for example:
tupler([1,2,3,4],[5,6,7])
returns:
[(1,5),(2,6),(3,7)]
or perhaps there is proper pythony way of doing this, or is there a generator similar???
I think you're looking for zip():
>>> zip([1,2,3,4],[5,6,7])
[(1, 5), (2, 6), (3, 7)]
have a look at the built-in zip function http://docs.python.org/library/functions.html#zip
it can also handle more than two lists, say n, and then creates n-tuples.
>>> zip([1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14])
[(1, 5, 9, 13), (2, 6, 10, 14)]
zip([1,2,3,4],[5,6,7])
--->[(1,5),(2,6),(3,7)]
args = [(1,5),(2,6),(3,7)]
zip(*args)
--->[1,2,3],[5,6,7]
The proper way is to use the zip function.
Alternativerly we can use list comprehensions and the built-in enumerate function
to achieve the same result.
>>> L1 = [1,2,3,4]
>>> L2 = [5,6,7]
>>> [(value, L2[i]) for i, value in enumerate(L1) if i < len(L2)]
[(1, 5), (2, 6), (3, 7)]
>>>
The drawback in the above example is that we don't always iterate over the list with the minimum length.

Categories

Resources