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.
Related
I want to do from list
['sw0005', 'sw0076', 'Gi1/2', 'sw0005', 'sw0076', 'Gi1/5']
Dict with tuple, which will looks like
{('sw0005','sw0076'):'Gi1/2', ('sw0005','sw0076'):'Gi1/5'}
How's better it can be done in python?
You could use an iter of the list to get the next element, and then the next two after that:
>>> lst = ['sw0005', 'sw0076', 'Gi1/2', 'sw0006', 'sw0076', 'Gi1/5']
>>> it = iter(lst)
>>> {(a, next(it)): next(it) for a in it}
{('sw0005', 'sw0076'): 'Gi1/2', ('sw0006', 'sw0076'): 'Gi1/5'}
Note: (a) I changes the list so the two tuples are not the same; (b) this will fail if the number of elements is not divisible by three.
As noted in comments, this only works properly a reasonably new version of Python. Alternatively, you can use a range with step and the index:
>>> {(lst[i], lst[i+1]): lst[i+2] for i in range(0, len(lst), 3)}
{('sw0005', 'sw0076'): 'Gi1/2', ('sw0006', 'sw0076'): 'Gi1/5'}
I made the iterable more readable
list1=['sw0005', 'sw0076', 'Gi1/2', 'sw0005', 'sw0076', 'Gi1/5']
queryable=iter(list1)
mylist=[]
for i in range(int(len(list1)/3)):
mylist.append({(next(queryable),next(queryable)):next(queryable)})
print(mylist)
I have a list in the format
unique_edges=[('SLT2', 'SDP1'),('GCD7', 'ATG34'),('MTH1', 'MTH1'),('ADY2', 'ADY2')]
and I need to use list comprehension (one line of code) to move the tuples with the same element twice (like ('MTH1', 'MTH1')) to a new list.
I'm thinking I will need to use something like
homo_dimers = list(map(tuple,unique_edges))
but I don't know how to use these functions to search for repeated elements within one tuple.
List comprehension to find tuples with same element:
homo_dimers = [(a, b) for a, b in unique_edges if a == b]
print(homo_dimers)
Prints:
[('MTH1', 'MTH1'), ('ADY2', 'ADY2')]
Or if your tuples contain more than 2 elements:
homo_dimers = [t for t in unique_edges if len(set(t)) == 1]
You can use if statements in list comprehensions:
unique_edges = [('SLT2', 'SDP1'), ('GCD7', 'ATG34'), ('MTH1', 'MTH1'),
('ADY2', 'ADY2')]
print([i for i in unique_edges if i[0] == i[1]])
homo_dimers = [i for i in unique_edges if i[0]==i[1]]
Output
[('MTH1', 'MTH1'), ('ADY2', 'ADY2')]
def move_from_list(item, old, new): #becaue we cant call multiple functions in a list comprehension line we create one funtion to move a tupil
old.remove(item)
new.append(item)
unique_edges=[('SLT2', 'SDP1'),('GCD7', 'ATG34'),('MTH1', 'MTH1'),('ADY2', 'ADY2')] #input list
homo_dimers=[]#empty list to fill with all the non-unique tupils
[move_from_list((a,b), unique_edges, homo_dimers) for a, b in unique_edges if a == b ] # the list comprehension line
print(homo_dimers) #[('MTH1', 'MTH1'), ('ADY2', 'ADY2')]
print(unique_edges) #[('SLT2', 'SDP1'), ('GCD7', 'ATG34'), ('ADY2', 'ADY2')]
I may have misunderstood the question. this code asumes you want to remove the non unique tupils from the list "unique_edges" AND add them to homo_dimers
sublist = [[32,999,15,329,679],[1738,100,55,1800,1469],["bruges","manchester","bristol","edinburgh","barcelona"]["Vienna","Stockholm","Berlin",Prague,"Dublin"]]
These sublists purposely have a mix of strings and integers for example but with 6 more sublists. Is there a way to search for example "Vienna" and return 4 as in "Vienna" is in the fourth sublist.
Many thanks
If you only have one level, you can just loop through this list and check whether the element is in this list, using the in keyword.
If, however, you have nested sublists with several levels, you might want to use a recursive function to scan all of them. The function finder() below scans through all nested lists and returns the indices of the lists in which the element was first encountered:
sublist = [[32,999,15,329,679],
[1738,100,55,1800,1469],
["bruges","manchester","bristol","edinburgh","barcelona"],
["Vienna","Stockholm","Berlin","Prague","Dublin"],
["Dog",["Cat","Parrot"]]]
def finder(nested,element):
for i in range(len(nested)):
if type(nested[i])==list:
f = finder(nested[i],element)
if type(f)==list:
return [i]+f
elif nested[i]==element:
return [i]
print(finder(sublist,"Vienna"))
print(finder(sublist,"Parrot"))
#Output:
#[3, 0]
#[4, 1, 1]
The output means that "Vienna" is in list 3, the 0th element. The element "Parrot" was in list 4, within list 1, the 1th element.
Here is a possible solution:
result = next((i for i, lst in enumerate(sublist) if 'Vienna' in lst), None)
In your specific case 3 is returned. If no suitable sublist is found (i.e., no sublists contains 'Vienna'), then None is returned.
You can use the enumerate function to elegantly solve your problem. However, keep in mind that Python uses 0-based indexing for arrays, so if you want to return 4 for "fourth sublist", you will need to add 1.
def find(nest, elem):
for idx, lst in enumerate(nest):
if elem in list:
return idx
sublist = [
[32,999,15,329,679],
[1738,100,55,1800,1469],
["bruges","manchester","bristol","edinburgh","barcelona"],
["Vienna","Stockholm","Berlin","Prague","Dublin"]]
print(find(sublist, "Vienna"))
To return 4:
def find(nest, elem):
for idx, lst in enumerate(nest):
if elem in list:
return idx + 1
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)]
>>>
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]