Flatten a list of lists of tuples - python

I have read several posts on the question "how to flatten lists of lists of lists ....". And I came up with this solution:
points = [[[(6,3)],[]],[[],[]]]
from itertools import chain
list(chain.from_iterable(points))
However my list looks sometimes like this:
[[[(6,3)],[]],[[],[]]]
Not sure if it is correct but I hope you understand.
The point is the leaf element is a tuple and when calling the above code it also removes the tuple and just returns [6,3].
So what could i do to just get [(6,3)] ?

How about this,
lists = [[[(6,3)],[]],[[],[]]]
r = [t for sublist in lists for l in sublist for t in l]
print(r)
# [(6, 3)]

maybe its not the best solution, but it works fine:
def flat(array):
result = []
for i in range(len(array)):
if type(array[i]) == list:
for j in flat(array[i]):
result.append(j)
else:
result.append(array[i])
return result
print flat([[[(6,3)],[]],[[],[]]] )
and the result is:
>>>
[(6, 3)]
>>>

Related

Python find all the different choices from list of list

I want to get all the different choices from a list of lists in python. for example, take a list like,
list=[[a,b,c],[a,d,e]]
I just want to select choices from one at each list and get all the possible different selections.
so above list possible choices look like,
[a,a]
[a,d]
[a,e]
[b,a]
[b,d]
[b,e]
[c,a]
[c,d]
[c,e]
without using any external library, how can I do this?
Easiest to implement with a recursive generator.
def yield_combos(lst):
if lst:
for el in lst[0]:
for combo in yield_combos(lst[1:]):
yield [el] + combo
else:
yield []
lst = [['a','b','c'], ['a','d','e']]
for combo in yield_combos(lst):
print(combo)
If you prefer the output as a list, you can always convert it into one:
print(list(yield_combos(lst)))
Minor notes:
I've called the variable lst where the question uses list; it's not a good idea to override a builtin, and in this case doing so would prevent the call to list from working.
I've set some string values in the caller for sake of a self-contained program (the question had a in place of 'a', etc).
The simplest way to do this is with two functions
def funcA(x, arr):
return [(x,c) for c in arr]
def funcB(arr1, arr2):
ans = []
for x in arr1:
ans.extend(funcA(x, arr2))
return ans
Call it whichever way to need:
funcB(your_list[0], your_list[1])
The most pythonic way is with itertools
you can simply use product from the itertools library like so:
my_list = [[a,b,c],[a,d,e]]
# will contain: [(a,a), (a,d)...]
all_combinations = list(itertools.product(*my_list))
The "*" unpacks the list into the lists it contains, its like writing:
# will contain: [(a,a), (a,d)...]
list(itertools.product([a,b,c],[a,d,e]))
It is worth mentioning that this works for any number of sublists.
my_list = [[a,b,c],[a,d,e], [1,2,3]]
# will contain: [(a,a,1), (a,a,2)...]
all_combinations = list(itertools.product(*my_list))
Hope that helps
you could use generators,
perm = [(i,j) for i in list[0] for j in list[1]]
furthermore if you could convert this into a generator object, if you memory concerns,
perm = ((i,j) for i in list[0] for j in list[1]])
I was told you have n lists and want to permutate all of them,
you can use a while loop
while(len(list)>1):
a = list.pop()
b = list.pop()
list.append([(i, j) for i in a for j in b])
or make a recursive function. Do note, that the answer will be list[0] and not list itself.
l=[['a','b','c'],['a','d','e']]
def combinations(L, tmp=None):
if tmp is None:
tmp = []
if L==[]:
print (tmp)
else:
for i in L[0]:
product(L[1:], tmp+[i])
combinations(l)
Does this help?

How to get all seperate all equal pairs from a list in python

I'm trying to write a python program to find all equal pairs in a list. So if there is a single repeat of an element in a list it would be added to the list.
[2,2,2,2,2] would become [2,2]
[8,8,8,2] would become [8]
[8,16,16,8] would become [8,16]
[2,0,2,4] would become [2]
[0,0,2,2] would become [0,2]
So far i have tried nesting for loops.
def pairfinder(newlist):
pairlist = []
for idx in range(len(newlist)):
for jdx in range(idx+1,len(newlist)):
if newlist[idx] == newlist[jdx]:
pairlist.append(newlist[idx])
break
return pairlist
This gives me the correct answer on some cases.. but not all
Sorry for not being clear enough.
print [a for a,b in zip(my_list[::2],my_list[1::2]) if a == b]
you may need to sort my_list first ...
my_list = sorted(my_list)
print [a for a,b in zip(my_list[::2],my_list[1::2]) if a == b]
Im not at all sure this solves your issue.
def do_this_weird_thing(a_list):
from itertools import groupby
for grp,item in groupby(sorted(a_list)):
item = list(item)
yield [grp] * (len(item)//2)
from itertools import chain
print list(chain.from_iterable(do_this_weird_thing([2,0,2,4])))

Searching List of Tuples by nth element in Python

So I have a list of tuples, with 3 elements each. Both the second and third elements are ints. For a value n, I need to return all the tuples that contain n as either the second or third element.
I'm not entirely sure how to do this, unfortunately. I'm sure it's not too complicated, but although there are some similar questions, I can't find any for this exact problem. Does anyone know how to go about this?
Thanks
You should be able to do this with a simple list comprehension. Something like:
[t for t in list_of_tuples if t[1] == n or t[2] == n]
Use a list comprehension with a simple if condition:
>>> lis=[('a',1,2),('b',2,2),('c',3,3),('d',3,1)]
>>> n=1
>>> [x for x in lis if n in x[1:3]] #[1:3] returns a sublist containing
# 2 & 3 element of each tuple
[('a', 1, 2), ('d', 3, 1)]
blist = [tup for tup in alist if n in tup[1:]]
The line above uses a list comprehension, and is equivalent to:
blist = []
for tup in alist:
if n in tup[1:]:
blist.append(tup)
tup[1:] returns a new tuple, consisting of the second and third items in the three item tuple tup.
In hindsight James Henstridge's example seems preferable, because t[1] == n or t[2] == n uses the existing tuple.

python - Common lists among lists in a list

I need to be able to find the first common list (which is a list of coordinates in this case) between a variable amount of lists.
i.e. this list
>>> [[[1,2],[3,4],[6,7]],[[3,4],[5,9],[8,3],[4,2]],[[3,4],[9,9]]]
should return
>>> [3,4]
If easier, I can work with a list of all common lists(coordinates) between the lists that contain the coordinates.
I can't use sets or dictionaries because lists are not hashable(i think?).
Correct, list objects are not hashable because they are mutable. tuple objects are hashable (provided that all their elements are hashable). Since your innermost lists are all just integers, that provides a wonderful opportunity to work around the non-hashableness of lists:
>>> lists = [[[1,2],[3,4],[6,7]],[[3,4],[5,9],[8,3],[4,2]],[[3,4],[9,9]]]
>>> sets = [set(tuple(x) for x in y) for y in lists]
>>> set.intersection(*sets)
set([(3, 4)])
Here I give you a set which contains tuples of the coordinates which are present in all the sublists. To get a list of list like you started with:
[list(x) for x in set.intersection(*sets)]
does the trick.
To address the concern by #wim, if you really want a reference to the first element in the intersection (where first is defined by being first in lists[0]), the easiest way is probably like this:
#... Stuff as before
intersection = set.intersection(*sets)
reference_to_first = next( (x for x in lists[0] if tuple(x) in intersection), None )
This will return None if the intersection is empty.
If you are looking for the first child list that is common amongst all parent lists, the following will work.
def first_common(lst):
first = lst[0]
rest = lst[1:]
for x in first:
if all(x in r for r in rest):
return x
Solution with recursive function. :)
This gets first duplicated element.
def get_duplicated_element(array):
global result, checked_elements
checked_elements = []
result = -1
def array_recursive_check(array):
global result, checked_elements
if result != -1: return
for i in array:
if type(i) == list:
if i in checked_elements:
result = i
return
checked_elements.append(i)
array_recursive_check(i)
array_recursive_check(array)
return result
get_duplicated_element([[[1,2],[3,4],[6,7]],[[3,4],[5,9],[8,3],[4,2]],[[3,4],[9,9]]])
[3, 4]
you can achieve this with a list comprehension:
>>> l = [[[1,2],[3,4],[6,7]],[[3,4],[5,9],[8,3],[4,2]],[[3,4],[9,9]]]
>>> lcombined = sum(l, [])
>>> [k[0] for k in [(i,lcombined.count(i)) for i in lcombined] if k[1] > 1][0]
[3, 4]

Double list Comprehension with range

I have a list in Python which I'm trying to print the first five elements out of it using list comprehension.
I understand that this has to be done using double list comprehensions. I have the following at the moment:
print [[x[i] for x in mylist] for i in range(0,5)]
This throws the following error: IndexError: tuple index out of range.
When I print each one separately, it works out fine. I do print mylist[0], print mylist[1] etc...
What is the issue here? I have a feeling that my entire double comprehension is not right. Now here's what I'm thinking:
[x for x in range(0,5)]
This creates a list of x's for each x in range(0,5). Since this is my index, I nested another list comprehension statement before that as above to do that over my specific list.
Any help is appreciated. Thanks!
mylist[:5] gives the first 5 elements of mylist. (If mylist has fewer than 5 elements in it, then mylist[:5] will return a list of length len(mylist).) Using a list comprehension here would be overkill.
Provided myList contains at least 5 elements, and you really want to use list comprehension, try this:
[print (mylist[i]) for i in range (0, 5)]
unutbu's is the best solution. Performing it using list comprehensions, you'd want
[mylist[i] for i in range(5)]
As for why you are getting the error, if myList is a list of tuples, look at it like this:
myList = [(0, 1), (1, 2), (2, 3)]
result = []
for i in range(5):
sub_result = []
# Here x will be (0, 1), etc.
for x in myList:
# Here you are referencing the ith element of your tuple
# If your tuple doesn't contain that many elements, you get the error
sub_result.append(x[i])
Therefore it is accessing your tuple and not your list. The other solutions all show how to correct this, so definitely vote for one them - this will hopefully just help figure out why it is causing an error :)
print [mylist[j] for j in [ i for i in range(5)]]
Although #unutbu's approach is much more readable.
You are trying to access indexes that out of range.
It means that your x tuple has length < 5.
It happens for data like [[1,2,3],[4,5,6]..]
x here would be [1,2,3], then [4,5,6] etc
when you try x[5] - you get Exception

Categories

Resources