appending list in python if with item from another list - python

I have two lists:
list1 = [('a', '1'),('b', '2'),('c', '3')
list2 = [('a', 'x'),('b', 'y'),('c', 'z')
I want to create:
list3 = [('a', '1', 'x'),('b', '2', 'y'),('c', '3', 'z')
I've tried .append, with no success:
list3 = list1.append(list2[1])

User list comprehension:
list1 = [('a', '1'),('b', '2'),('c', '3')]
list2 = [('a', 'x'),('b', 'y'),('c', 'z')]
list3= [(list1[i][0],list1[i][1],list2[i][1]) for i in range(len(list1))]
print(list3)
Output:
[('a', '1', 'x'), ('b', '2', 'y'), ('c', '3', 'z')]

You can use zip:
list1 = [('a', '1'),('b', '2'),('c', '3')]
list2 = [('a', 'x'),('b', 'y'),('c', 'z')]
new_result = [(a, c, d) for (a, c), (_, d) in zip(list1, list2)]
Output:
[('a', '1', 'x'), ('b', '2', 'y'), ('c', '3', 'z')]

You can use union.
list1 = [('a', '1'),('b', '2'),('c', '3')]
list2 = [('a', 'x'),('b', 'y'),('c', 'z')]
list3 = []
for i in range(len(list1)):
for j in range(len(list2)):
if(i == j):
list3.append(set(list1[i]) | set(list2[j]))
break;
Output:
[{'a', 'x', '1'}, {'y', '2', 'b'}, {'3', 'c', 'z'}]

Related

Find unique elements in the lists of lists of objects in Python

I have list of objects in Python. Each object contains own list. The list contains some categories of that object. Every list contains exactly 15 elements (could be letter, number or symbol -) eg.
['A', 'A', '1', '-', ... , 'B'] or ['-', 'C', 'X', '-', ... , 'D']
My goal is to find unique values for each category or more precisely of each position in the list, ideally stored in the form of dictionary, for example something like this:
{0: {'A', '-'} 1: {'A', 'C'} ... }
So I need to go through of all objects in the list and save those unique values. Is there a way to do this in elegant, pythonic way?
Thanks for all answers.
you can pair objects position wise with each other with zip
>>> a=['A', 'A', '1', '-', 'B']
>>> b=['-', 'C', 'X', '-', 'D']
>>> list(zip(a,b))
[('A', '-'), ('A', 'C'), ('1', 'X'), ('-', '-'), ('B', 'D')]
>>>
and to get that dictionary from your sample you can add enumerate to the mix
>>> dict(enumerate(zip(a,b)))
{0: ('A', '-'), 1: ('A', 'C'), 2: ('1', 'X'), 3: ('-', '-'), 4: ('B', 'D')}
>>>
and to get the unique such pair you can use set to remove duplicates
>>> c=['A', 'A', '1', '-', 'B', 'A', 'A', '1', '-', 'B']
>>> d=['-', 'C', 'X', '-', 'D', '-', 'C', 'X', '-', 'D']
>>> list(zip(c,d))
[('A', '-'), ('A', 'C'), ('1', 'X'), ('-', '-'), ('B', 'D'), ('A', '-'), ('A', 'C'), ('1', 'X'), ('-', '-'), ('B', 'D')]
>>> set(zip(c,d))
{('A', '-'), ('1', 'X'), ('A', 'C'), ('-', '-'), ('B', 'D')}
>>>

Zip operator parameter based on loop condition

I want to increase the number of items I zip in a string based on a for loop.
So for example, this is the code
s = "abcde"
for i in range(1, len(s)):
#if i = 1, then this should be the code statement
l = zip(s, s[1:]) #list(l) = [('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'e')]
#if i = 2, then
l = zip(s, s[1:], s[2:]) #list(l) = [('a', 'b', 'c'), ('b', 'c', 'd'), ('c', 'd', 'e')]
#if i = 3, then
l = zip(s, s[1:], s[2:], s[3:]) #list(l) = [('a', 'b', 'c', 'd'), ('b', 'c', 'd', 'e')]
Observe that for any given i, there are i + 1 iterables in the zip operator.
>>> s = '123456'
>>>
>>> for n in range(1, len(s)):
print(list(zip(*[s[i:] for i in range(0,n+1)])))
[('1', '2'), ('2', '3'), ('3', '4'), ('4', '5'), ('5', '6')]
[('1', '2', '3'), ('2', '3', '4'), ('3', '4', '5'), ('4', '5', '6')]
[('1', '2', '3', '4'), ('2', '3', '4', '5'), ('3', '4', '5', '6')]
[('1', '2', '3', '4', '5'), ('2', '3', '4', '5', '6')]
[('1', '2', '3', '4', '5', '6')]
[s[i:] for i in range(0,n+1)]
Is a list comprehension that creates a list of slices of s.
For n=2 it creates the list [s[0:], s[1:], s[2:]].
It can be written as a regular for loop:
l = []
for i in range(0,n+1):
#print(i, 's[{}:]'.format(i))
l.append(s[i:])
Using the regular for loop used in your solution would be:
for n in range(1, len(s)):
#print('n:{}'.format(n), '**********')
l = []
for i in range(0, n+1):
l.append(s[i:])
#print(l)
print(list(zip(*l)))
Here is a function adapted from an itertools recipe that does something similar.
import itertools
def nwise(iterable, n=2):
"s -> (s0,s1), (s1,s2), (s2, s3), ... for n=2"
iterables = itertools.tee(iterable, n)
# advance each iterable to the appropriate starting point
for i, thing in enumerate(iterables[1:],1):
for _ in range(i):
next(thing, None)
return zip(*iterables)
For your use:
for n in range(1, len(s)):
print(list(nwise(s, n+1)))

Get every pair-wise combination of values between two lists

Let's say I have two lists;
a = ['A', 'B', 'C', 'D']
b = ['1', '2', '3', '4']
I know I can get every permutation of these two lists like so:
for r in itertools.product(a, b): print (r[0] + r[1])
But what I'm looking for is every pairwise combination stored in a tuple. So, for example, some combinations would be:
[(A, 1), (B, 2), (C, 3), (D, 4)]
[(A, 1), (B, 3), (C, 2), (D, 4)]
[(A, 1), (B, 4), (C, 3), (D, 2)]
[(A, 1), (B, 3), (C, 4), (D, 2)]
[(A, 1), (B, 2), (C, 4), (D, 3)]
So it would iterate through every possible combination so that no letter has the same number value. I'm at a loss for an efficient way to do this (particularly since I need to scale this to three lists in my actual example)
We can make permutations of one of the lists (for example here the latter one), and then zip each permutation together with the first list, like:
from functools import partial
from itertools import permutations
def pairwise_comb(xs, ys):
return map(partial(zip, xs), permutations(ys))
or in case all subelements should be lists (here these are still iterables that can take a specific shape when you "materialize" these):
from functools import partial
from itertools import permutations
def pairwise_comb(xs, ys):
return map(list, map(partial(zip, xs), permutations(ys)))
For the given sample input, we obtain:
>>> for el in pairwise_comb(a, b):
... print(list(el))
...
[('A', '1'), ('B', '2'), ('C', '3'), ('D', '4')]
[('A', '1'), ('B', '2'), ('C', '4'), ('D', '3')]
[('A', '1'), ('B', '3'), ('C', '2'), ('D', '4')]
[('A', '1'), ('B', '3'), ('C', '4'), ('D', '2')]
[('A', '1'), ('B', '4'), ('C', '2'), ('D', '3')]
[('A', '1'), ('B', '4'), ('C', '3'), ('D', '2')]
[('A', '2'), ('B', '1'), ('C', '3'), ('D', '4')]
[('A', '2'), ('B', '1'), ('C', '4'), ('D', '3')]
[('A', '2'), ('B', '3'), ('C', '1'), ('D', '4')]
[('A', '2'), ('B', '3'), ('C', '4'), ('D', '1')]
[('A', '2'), ('B', '4'), ('C', '1'), ('D', '3')]
[('A', '2'), ('B', '4'), ('C', '3'), ('D', '1')]
[('A', '3'), ('B', '1'), ('C', '2'), ('D', '4')]
[('A', '3'), ('B', '1'), ('C', '4'), ('D', '2')]
[('A', '3'), ('B', '2'), ('C', '1'), ('D', '4')]
[('A', '3'), ('B', '2'), ('C', '4'), ('D', '1')]
[('A', '3'), ('B', '4'), ('C', '1'), ('D', '2')]
[('A', '3'), ('B', '4'), ('C', '2'), ('D', '1')]
[('A', '4'), ('B', '1'), ('C', '2'), ('D', '3')]
[('A', '4'), ('B', '1'), ('C', '3'), ('D', '2')]
[('A', '4'), ('B', '2'), ('C', '1'), ('D', '3')]
[('A', '4'), ('B', '2'), ('C', '3'), ('D', '1')]
[('A', '4'), ('B', '3'), ('C', '1'), ('D', '2')]
[('A', '4'), ('B', '3'), ('C', '2'), ('D', '1')]
This thus results in 24 possible ways to combine this, since the order of 'A', 'B', 'C' and 'D' remains fixed, and the 4 characters can be assigned in 4! ways, or 4! = 4×3×2×1 = 24.
It may be a lot easier than you think. What about:
import itertools
a = ['A', 'B', 'C', 'D']
b = ['1', '2', '3', '4']
for aperm in itertools.permutations(a):
for bperm in itertools.permutations(b):
print(list(zip(aperm, bperm)))
First outputs:
[('A', '1'), ('B', '2'), ('C', '3'), ('D', '4')]
[('A', '1'), ('B', '2'), ('C', '4'), ('D', '3')]
[('A', '1'), ('B', '3'), ('C', '2'), ('D', '4')]
[('A', '1'), ('B', '3'), ('C', '4'), ('D', '2')]
[('A', '1'), ('B', '4'), ('C', '2'), ('D', '3')]
[('A', '1'), ('B', '4'), ('C', '3'), ('D', '2')]
[('A', '2'), ('B', '1'), ('C', '3'), ('D', '4')]
[('A', '2'), ('B', '1'), ('C', '4'), ('D', '3')]
[('A', '2'), ('B', '3'), ('C', '1'), ('D', '4')]
...
(There are 576 lines printed for these two 4-element lists)
Edit: If you want to generalize this to more iterables, you could do something like:
import itertools
a = ['A', 'B', 'C', 'D']
b = ['1', '2', '3', '4']
gens = [itertools.permutations(lst) for lst in (a,b)]
for perms in itertools.product(*gens):
print(list(zip(*perms)))
Which outputs the same thing, but could be easily extended, e.g.
import itertools
a = ['A', 'B', 'C', 'D']
b = ['1', '2', '3', '4']
c = ['W', 'X', 'Y', 'Z']
gens = [itertools.permutations(lst) for lst in (a,b,c)] # add c
for perms in itertools.product(*gens): # no change
print(list(zip(*perms))) # ''
You can use recursion with yield for a no-import solution:
a = ['A', 'B', 'C', 'D']
b = ['1', '2', '3', '4']
def combinations(d, current = []):
if len(current) == 4:
yield current
elif filter(None, d):
for i in d[0]:
_d0, _d1 = [c for c in d[0] if c != i], [c for c in d[1] if c != d[1][0]]
yield from combinations([_d0, _d1] , current+[[i, d[1][0]]])
for i in combinations([a, b]):
print(i)
Output:
[['A', '1'], ['B', '2'], ['C', '3'], ['D', '4']]
[['A', '1'], ['B', '2'], ['D', '3'], ['C', '4']]
[['A', '1'], ['C', '2'], ['B', '3'], ['D', '4']]
[['A', '1'], ['C', '2'], ['D', '3'], ['B', '4']]
[['A', '1'], ['D', '2'], ['B', '3'], ['C', '4']]
[['A', '1'], ['D', '2'], ['C', '3'], ['B', '4']]
[['B', '1'], ['A', '2'], ['C', '3'], ['D', '4']]
[['B', '1'], ['A', '2'], ['D', '3'], ['C', '4']]
[['B', '1'], ['C', '2'], ['A', '3'], ['D', '4']]
[['B', '1'], ['C', '2'], ['D', '3'], ['A', '4']]
[['B', '1'], ['D', '2'], ['A', '3'], ['C', '4']]
[['B', '1'], ['D', '2'], ['C', '3'], ['A', '4']]
[['C', '1'], ['A', '2'], ['B', '3'], ['D', '4']]
[['C', '1'], ['A', '2'], ['D', '3'], ['B', '4']]
[['C', '1'], ['B', '2'], ['A', '3'], ['D', '4']]
[['C', '1'], ['B', '2'], ['D', '3'], ['A', '4']]
[['C', '1'], ['D', '2'], ['A', '3'], ['B', '4']]
[['C', '1'], ['D', '2'], ['B', '3'], ['A', '4']]
[['D', '1'], ['A', '2'], ['B', '3'], ['C', '4']]
[['D', '1'], ['A', '2'], ['C', '3'], ['B', '4']]
[['D', '1'], ['B', '2'], ['A', '3'], ['C', '4']]
[['D', '1'], ['B', '2'], ['C', '3'], ['A', '4']]
[['D', '1'], ['C', '2'], ['A', '3'], ['B', '4']]
[['D', '1'], ['C', '2'], ['B', '3'], ['A', '4']]

All combinations across multiple lists

Given a multidimensional list (a list of lists) I would like to get all possible combinations of the sub lists items.
For example an input of:
my_list = [
['a', 'b'], ['1', '2'], ['#', '&']
]
Would result in:
result = [
['a'],
['b'],
['1'],
['2'],
['#'],
['&'],
['a', '1'],
['a', '2'],
['a', '#'],
['a', '&']
['b', '1'],
['b', '2'],
['b', '#'],
['b', '&'],
['a', '1', '#'],
['a', '1', '&'],
['a', '2', '#'],
['a', '2', '&'],
...]
I tried using itertools.product(*list) but that results in a combination of all items without the smaller sets of combinations. It seems that itertools.combinations, itertools.permutations, etc don't quite give what I am looking for.
Is there a quick way of doing this?
In that case you first iterate over all possible lengths. For each length you pick all possible combinations of lists, and for each of these combinations you use itertools.product:
def weird_product(*data):
for i in range(1,len(data)+1):
for subdata in itertools.combinations(data,i):
for elem in itertools.product(*subdata):
yield elem
This generates:
>>> list(weird_product(*data))
[('a',), ('b',), ('1',), ('2',), ('#',), ('&',), ('a', '1'), ('a', '2'), ('b', '1'), ('b', '2'), ('a', '#'), ('a', '&'), ('b', '#'), ('b', '&'), ('1', '#'), ('1', '&'), ('2', '#'), ('2', '&'), ('a', '1', '#'), ('a', '1', '&'), ('a', '2', '#'), ('a', '2', '&'), ('b', '1', '#'), ('b', '1', '&'), ('b', '2', '#'), ('b', '2', '&')]
or more elegantly formatted:
>>> list(weird_product(*data))
[('a',),
('b',),
('1',),
('2',),
('#',),
('&',),
('a', '1'),
('a', '2'),
('b', '1'),
('b', '2'),
('a', '#'),
('a', '&'),
('b', '#'),
('b', '&'),
('1', '#'),
('1', '&'),
('2', '#'),
('2', '&'),
('a', '1', '#'),
('a', '1', '&'),
('a', '2', '#'),
('a', '2', '&'),
('b', '1', '#'),
('b', '1', '&'),
('b', '2', '#'),
('b', '2', '&')]

Lists and Tuples

Let us consider
x = ['1', '2', '3', '4', '5']
y = ['a', 'b', 'c', 'd', 'e']
How do I get the required output z?
z = [('1', 'a') , ('b', '2') , ('c', '3') , ('d', '4') , ('e', '5')]
You're looking for zip:
>>> x = ['1', '2', '3', '4', '5']
>>> y = ['a', 'b', 'c', 'd', 'e']
>>> z = zip(x, y)
>>> z
[('1', 'a'), ('2', 'b'), ('3', 'c'), ('4', 'd'), ('5', 'e')]
It's called zip:
z = zip(x, y)

Categories

Resources