How to extract tuples from sublists? - python

I have tried many ways to solve this but instead of getting the tuples, I get individual elements like
'[' , '(' ,'a'.
My input:[[('a','b')],[('b','c'),('d','e')]]
Required output:('a','b')
('b','c')('d','e')
Is there any method to solve this?

You can try unpacking:
>>> inp = [[('a','b')],[('b','c'),('d','e')]]
>>> for inner_list in inp:
... print(*inner_list, sep='')
('a', 'b')
('b', 'c')('d', 'e')

with list comprenhension indexing two times.
out = [tup for l in myList for tup in l]
you get:
[('a', 'b'), ('b', 'c'), ('d', 'e')]
if you want to print each tupla individually just:
for i in out: print(i)

Related

nested value from nested index python

I am trying to get an output list from nested list based on nested indices.
Input:
list_a = [(a,b,c,d), (f,g), (n,p,x)]
sub_index_a = [(0,2),(1),(0,1)]
Output:
output_list = [(a,c), (g), (n,p)]
list_a = [('a', 'b', 'c', 'd'), ('f', 'g'), ('n', 'p', 'x')]
sub_index_a = [(0, 2), (1,), (0, 1)]
def check(i, e):
r = []
for ee in e:
r.append(list_a[i][ee])
return tuple(r)
outputlist = [check(i, e) for i, e in enumerate(sub_index_a)]
print(outputlist)
This evaluates to
[('a', 'c'), ('g',), ('n', 'p')]
well having ("g") just evaluates to "g",the actual tuple of that would look like ("g",) (tuple(["g"])), same as (1) but I think found a half-decent workaround? Hopefully, this is your desired solution.
list_a = [('a','b','c','d'), ('f','g'), ('n','p','x')]
sub_index_a = [(0,2),(1),(0,1)]
print([tuple([list_a[x][indx] for indx in i]) if type(i) in [tuple, list] else list_a[x][i] for x,i in enumerate(sub_index_a)])
[('a', 'c'), 'g', ('n', 'p')]
if you want everything returned as a tuple you can modify the comprehension to:
print([tuple([list_a[x][indx] for indx in i]) if type(i) in [tuple, list] else tuple([list_a[x][i]]) for x,i in enumerate(sub_index_a)])
[('a', 'c'), ('g',), ('n', 'p')]
note:
if you want everything to be nested (with a single element) you would want a list of lists; E.g. [[0,2],[1],[0,1]]
Use zip and a nested comprehension:
list_a = [("a","b","c","d"), ("f","g"), ("n","p","x")]
sub_index_a = [(0,2),(1,),(0,1)] # note the comma in the second tuple
output_list = [tuple(sub[i] for i in i_s) for sub, i_s in zip(list_a, sub_index_a)]
# [('a', 'c'), ('g',), ('n', 'p')]

Convert list of tuples such that [(a,b,c)] converts to [(a,b),(a,c)]

Thoughts on how I would do this? I want the first value in the tuple to pair with each successive value. This way each resulting tuple would be a pair starting with the first value.
I need to do this: [(a,b,c)] --> [(a,b),(a,c)]
You can try this.
(t,)=[('a','b','c')]
[(t[0],i) for i in t[1:]]
# [('a', 'b'), ('a', 'c')]
Using itertools.product
it=iter(('a','b','c'))
list(itertools.product(next(it),it))
# [('a', 'b'), ('a', 'c')]
Using itertools.repeat
it=iter(('a','b','c'))
list(zip(itertools.repeat(next(it)),it))
# [('a', 'b'), ('a', 'c')]
a = [('a','b','c')]
a = a[0]
a = [tuple([a[0], a[index]]) for index in range(1, len(a))]
Try this !
A solution that uses itertools's combinations module.
from itertools import combinations
arr = (['a','b','c'])
for i in list(combinations(arr, 2)):
if(i[0]==arr[0]):
print(i ,end = " ")
This would give a solution ('a', 'b') ('a', 'c')
You can just append pairs of tuples to a list:
original = [(1,2,3)]
def makePairs(lis):
ret = []
for t in lis:
ret.append((t[0],t[1]))
ret.append((t[0],t[2]))
return ret
print(makePairs(original))
Output:
[(1, 2), (1, 3)]
If your tuples are arbitrary length you can write a simple generator:
def make_pairs(iterable):
iterator = iter(iterable)
first = next(iterator)
for item in iterator:
yield first, item
example result:
my_tuple = ('a', 'b', 'c', 'd')
list(make_pairs(my_tuple))
Out[170]: [('a', 'b'), ('a', 'c'), ('a', 'd')]
This is a memory-efficient solution.

Python: Filter in tuples

I have two lists of tuples. I want a new list with every member of l2 and every member of l1 that does not begin with the same element from l2.
I used a for loop and my output is ok.
My question is: How can I use the filter function or a list comprehension?
def ov(l1, l2):
l3=l1.copy()
for i in l2:
for j in l1:
if i[0]==j[0]:
l3.pop(l3.index(j))
print (l3+l2)
ov([('c','d'),('c','e'),('a','b'),('a', 'd')], [('a','c'),('b','d')])
The output is:
[('c', 'd'), ('c', 'e'), ('a', 'c'), ('b', 'd')]
If I understand correctly, this should be the straight forward solution:
>>> l1 = [('c','d'),('c','e'),('a','b'),('a', 'd')]
>>> l2 = [('a','c'),('b','d')]
>>>
>>> starters = set(x for x, _ in l2)
>>> [(x, y) for x, y in l1 if x not in starters] + l2
[('c', 'd'), ('c', 'e'), ('a', 'c'), ('b', 'd')]
This can be generalized to work with longer tuples with extended iterable unpacking.
>>> starters = set(head for head, *_ in l2)
>>> [(head, *tail) for head, *tail in l1 if head not in starters] + l2
[('c', 'd'), ('c', 'e'), ('a', 'c'), ('b', 'd')]
Here is an approach using filter:
from operator import itemgetter
f = itemgetter(0)
zval = set(map(itemgetter(0), l2))
list(filter(lambda tup: f(tup) not in zval, l1)) + l2
[('c', 'd'), ('c', 'e'), ('a', 'c'), ('b', 'd')]
Or:
def parser(tup):
return f(tup) not in zval
list(filter(parser, l1)) + l2
[('c', 'd'), ('c', 'e'), ('a', 'c'), ('b', 'd')]
Filter is a function which returns a list for all True returns of a function, being used as filter(function(), iterator).
def compare(one, two):
for i in two:
if i[0]==one[0]:
print("yes:", one,two)
return False
return True
l1 = [('c','d'),('c','e'),('a','b'),('a', 'd')]
l2 = [('a','c'),('b','d')]
one_liner = lambda n: compare(l1[n], l2) # where n is the tuple in the first list
lets_filter = list(filter(one_liner, range(len(l1))))
final_list = l2.copy()
for i in lets_filter:
final_list.append(l1[i])
print(final_list)
I made this as a way to do it. Lambda might be a bit confusing, alert if you don't understand it, and I'll remake it.
List comprehension is a "ternary operator", if you're familiar with those, in order to make a list in a one-liner.
l1 = [('c','d'),('c','e'),('a','b'),('a', 'd')]
l2 = [('a','c'),('b','d')]
l3 = [l1[n] for n in range(len(l1)) if l1[n][0] not in [l2[i][0] for i in range(len(l2))]]+l2
print(l3)
This code does the trick, but is overwhelming at first. Let me explain what it does.
l1[n] for n in range(len(l1) goes through all the pairs in l1, in order to see if we can add them. This is done when the if returns True.
l1[n][0] not in takes the first item, and returns True if doesn't exist in any of the elements of the following list.
[l2[i][0] for i in range(len(l2))] makes a list from all the first elements of l2.
+l2 is added, as requested.
As a bonus, I'm going to explain how to use else in the same scenario, in case you wanted another result.
l1 = [('c','d'),('a','b'),('c','e'),('a', 'd')]
l2 = [('a','c'),('b','d')]
l3 = [l1[n] if l1[n][0] not in [l2[i][0] for i in range(len(l2))] else ("not", "you") for n in range(len(l1))]+l2
print(l3)
As you can see, I had to switch the order of the operators, but works as it should, adding them in the correct order of l1 (which I changed for the sake of showing).

How do I take a list of strings and return a list of pairs?

[’A:2’,’B:2’,’C:2’,’D:1’]
How do you get rid of the colon and replace it with the comma? So, how do you get the above code and make it look like the one below?
[(’A’, 2), (’B’, 2), (’C’, 2), (’D’, 1)]
Using a list comprehension:
[(y[0], int(y[1])) for y in [x.split(':') for x in ['A:2', 'B:2', 'C:2', 'D:1']]]
Split each of the strings in the list on ::
>>> L = ['A:2','B:2','C:2','D:1']
>>> [tuple(x.split(':')) for x in L]
[('A', '2'), ('B', '2'), ('C', '2'), ('D', '1')]
you might want to look up map function and how split() works.
lambda allows you to craft your own function which map applies on or 'maps' to every single element of the iterable L
L = [’A:2’,’B:2’,’C:2’,’D:1’]
result = map(lambda x: tuple(x.split(':')), L)
if you wanted the values of the letters to be of type int, then:
result = map(lambda x: (x.split(':')[0], int(x.split(':')[0])), L)
>>> items = ['A:2', 'B:2', 'C:2', 'D:1']
>>> [(a, int(b)) for a, b in (item.split(':') for item in items)]
[('A', 2), ('B', 2), ('C', 2), ('D', 1)]

Removing duplicates from tuples within a list

I have a list of tuples:
lst = [('a','b'), ('c', 'b'), ('a', 'd'), ('e','f'), ('a', 'b')]
I want the following output list:
output = [('a','b'), ('e','f')]
i.e I want to compare the elements of first tuple with remaining tuples and remove the tuple which contains either one or more duplicate elements.
My attempt:
I was thinking of using for loops, but that wont be feasible once i have very large list. I browsed through following posts but could not get the right solution:
Removing duplicates members from a list of tuples
How do you remove duplicates from a list in whilst preserving order?
If somebody could guide me the right direction, it will be very helpful. Thanks!
Assuming that you want "duplicates" of all elements to be suppressed, and not just the first one, you could use:
lst = [('a','b'), ('c', 'b'), ('a', 'd'), ('e','f'), ('a', 'b')]
def merge(x):
s = set()
for i in x:
if not s.intersection(i):
yield i
s.update(i)
gives
>>> list(merge(lst))
[('a', 'b'), ('e', 'f')]
>>> list(merge([('a', 'b'), ('c', 'd'), ('c', 'e')]))
[('a', 'b'), ('c', 'd')]
>>> list(merge([('a', 'b'), ('a', 'c'), ('c', 'd')]))
[('a', 'b'), ('c', 'd')]
Sets should help:
>>> s = map(set, lst)
>>> first = s[0]
>>> [first] + [i for i in s if not i & first]
[set(['a', 'b']), set(['e', 'f'])]
Or with ifilterfalse:
>>> from itertools import ifilterfalse
>>> s = map(set, lst)
>>> [first] + list(ifilterfalse(first.intersection, s))
[set(['a', 'b']), set(['e', 'f'])]

Categories

Resources