Create a list only considering the elements of another list - python

I want to make a list from the elements of one list (base) but only considering the elements of another list (other).
The base list is:
base = [['A', 'B'], ['B'], ['A', 'B', 'C', 'D', 'E'], ['B'], ['A', 'B', 'C'], ['A'], ['B', 'C'], ['A', 'B'], ['C', 'A', 'B'], ['A'], ['B', 'C']]
The other list is:
other = ['A', 'B']
The expected result is:
expected = [['A', 'B'], ['B'], ['A', 'B'], ['B'], ['A', 'B'], ['A'], ['B'], ['A', 'B'], ['A', 'B'], ['A'], ['B']]
Is there a pythonic way of doing this?

Like this:
base = [['A', 'B'], ['B'], ['A', 'B', 'C', 'D', 'E'], ['B'], ['A', 'B', 'C'], ['A'], ['B', 'C'], ['A', 'B'], ['C', 'A', 'B'], ['A'], ['B', 'C']]
other = ['A', 'B']
expected = [[i for i in l if i in other] for l in base]
print(expected)
Output:
[['A', 'B'],
['B'],
['A', 'B'],
['B'],
['A', 'B'],
['A'],
['B'],
['A', 'B'],
['A', 'B'],
['A'],
['B']]
Breaking it down: expected = [[i for i in l if i in other] for l in base] is the equivalent of:
expected = []
for l in base: # For every list in base
lst = [] # There will be a list in expected
for i in l: # For every element in l
if i in other: # If the element is in base
lst.append(i) # Append the element to the list that will go into expected
expected.append(lst) # Append lst to expected

Using list comprehension:
result = [[x for x in arr if x in other] for arr in base]
One quick optimization can be applied here. Set data structure can be used here to store other for the O(1) lookup.
So, the improved version:
otherSet = set(other)
result = [[x for x in arr if x in otherSet] for arr in base]

You can use map and filter:
list(map(lambda x: list(filter(lambda f: f in other, x)), base))
[['A', 'B'],
['B'],
['A', 'B'],
['B'],
['A', 'B'],
['A'],
['B'],
['A', 'B'],
['A', 'B'],
['A'],
['B']]

Related

adding list as a sublist in a nested list at the start of the nested list Python

given a nested list:
input_list = [['c', 'd'], ['e', 'f']]
addition_to_input_list = ['a', 'b']
required_output = [['a', 'b'], ['c', 'd'], ['e', 'f']]
for my current program, it is enough to put the addition at the start, in the future I may have to also put the addition at a specific index in the nested list.
Thanks in advance
This is a simple list insertion. It doesn't matter that the elements are lists themselves. So, this will do it:
input_list.insert( 0, addition_to_input_list )
Or you can build a new list:
required_output = [addition_to_input_list] + input_list
Proof that both options work:
>>> input_list = [['c', 'd'], ['e', 'f']]
>>> addition_to_input_list = ['a', 'b']
>>> input_list.insert(0,addition_to_input_list)
>>> input_list
[['a', 'b'], ['c', 'd'], ['e', 'f']]
>>> input_list = [['c', 'd'], ['e', 'f']]
>>> [addition_to_input_list]+input_list
[['a', 'b'], ['c', 'd'], ['e', 'f']]
>>>

Python list of all possible n-member combinations given master list

Given a list l:
l = ['A', 'B', 'C']
How can I write a function that returns all possible unique combinations of n members, in a list of lists? Order doesn't matter for uniqueness. The outputs in this example would be (the order is also unimportant in the output):
my_function(list=l, n=1)
[['A'], ['B'], ['C']]
my_function(list=l, n=2)
[['A', 'B'], ['A', 'C'], ['B', 'C']]
my_function(list=l, n=3)
[['A', 'B', 'C']]
You can use itertools.combinations for the task:
from itertools import combinations
l = ['A', 'B', 'C']
def my_function(lst, n):
rv = []
for c in combinations(lst, n):
rv.append(list(c))
return rv
print(my_function(l, 1))
print(my_function(l, 2))
print(my_function(l, 3))
Prints:
[['A'], ['B'], ['C']]
[['A', 'B'], ['A', 'C'], ['B', 'C']]
[['A', 'B', 'C']]
Without Itertools:
a=['A','B','C']
def combi(a):
result = [[]]
for x in a:
result.extend([subset + [x] for subset in result])
return result
print(combi(a))

How can I zip every element of a nested list?

I have two nested lists:
l = [
['a', 'b', 'c'],
['d', 'e', 'f']
]
l2 = [
['a', 'b', 'c'],
['d', 'e', 'f']
]
I want to merge every element of the two nested list into a new seperate list like this:
nl = [
['a', 'a'], ['b', 'b'], ['c', 'c'],
['d', 'd'], ['e','e'], ['f','f']
]
But my code:
r = []
r+= [[j + ' , '+ k] for j,k in zip(l[i],l2[i])]
Just gives me the last list in the nested list as result:
nl = [['f','f']]
How can I change my code to get everything in the two nested lists in nl ?
from itertools import chain
l = [
['a', 'b', 'c'],
['d', 'e', 'f']
]
l2 = [
['a', 'b', 'c'],
['d', 'e', 'f']
]
nl = list(map(list, zip(chain(*l), chain(*l2))))
Output:
[
['a', 'a'],
['b', 'b'],
['c', 'c'],
['d', 'd'],
['e', 'e'],
['f', 'f']
]

python - how to convert a nested list to a list of all individual sub-lists

I have a Nested List like this:
l = [['A', ['A', 'B', ['A', 'B', 'C'], ['A', 'B', 'D']], ['A', 'D', ['A', 'D', 'A']], ['A', 'C', ['A', 'C', 'B'], ['A', 'C', 'A']], ['A', 'A', ['A', 'A', 'D']]]]
I want to separate it to a List of all individual lists like this:
k = [['A'], ['A', 'B'], ['A', 'B', 'C'], ['A', 'B', 'D'], ['A', 'D'], ['A', 'D', 'A'], ['A', 'C'], ['A', 'C', 'B'], ['A', 'C', 'A'], ['A', 'A'], ['A', 'A', 'D']]
I tried this by creating the following function:
def un_nest(l):
k=[]
for item in l:
if type(item) is list:
un_nest(item)
else:
k+=[item]
print(k)
I got the required output, but I don't know how to convert it to list.
the output I got is:
['A', 'B', 'C']
['A', 'B', 'D']
['A', 'B']
['A', 'D', 'A']
['A', 'D']
['A', 'C', 'B']
['A', 'C', 'A']
['A', 'C']
['A', 'A', 'D']
['A', 'A']
['A']
[]
this was output in the shell, (I know this is because of print function), but i have no idea how to get the list from this. As I need to do some operation the the required list for final output.
I am using Python 3.4.1
Any hint will help. Thanks in advance
Edit:
Its more like I want to, separate all the strings and sub-list from 'l', to another list.
You could return a list as the result at the current nesting level and join together the nested results using extend.
l = [['A', ['A', 'B', ['A', 'B', 'C'], ['A', 'B', 'D']], ['A', 'D', ['A', 'D', 'A']], ['A', 'C', ['A', 'C', 'B'], ['A', 'C', 'A']], ['A', 'A', ['A', 'A', 'D']]]]
def un_nest(l):
r = []
k = []
for item in l:
if type(item) is list:
r.extend(un_nest(item))
else:
k.append(item)
if k:
r.insert(0, k)
return r
print(un_nest(l))
outputs:
[['A'], ['A', 'B'], ['A', 'B', 'C'], ['A', 'B', 'D'], ['A', 'D'], ['A', 'D', 'A'], ['A', 'C'], ['A', 'C', 'B'], ['A', 'C', 'A'], ['A', 'A'], ['A', 'A', 'D']]

Sorting a list in Python without repeat previous item

Well
I have a unique combination of elements (A B C D E F)
from itertools import combinations
data = ['A', 'B', 'C', 'D', 'E', 'F'];
comb = combinations(data, 2);
d = [];
for i in comb:
d.append([i[0], i[1]]);
print d
This returns to me:
[['A', 'B'],
['A', 'C'],
['A', 'D'],
['A', 'E'],
['A', 'F'],
['B', 'C'],
['B', 'D'],
['B', 'E'],
['B', 'F'],
['C', 'D'],
['C', 'E'],
['C', 'F'],
['D', 'E'],
['D', 'F'],
['E', 'F']]
The question is, how to sort this in a way that the line N do not repeat element [0] or element [1] of line (N-1)...in a simpler way:
AB (This line can have any element)
CD (This line can't have A or B)
EF (This line can't have C or D)
AC (This line can't have E or F)
...
mylist= [['A', 'B'],
['A', 'C'],
['A', 'D'],
['A', 'E'],
['A', 'F'],
['B', 'C'],
['B', 'D'],
['B', 'E'],
['B', 'F'],
['C', 'D'],
['C', 'E'],
['C', 'F'],
['D', 'E'],
['D', 'F'],
['E', 'F']]
a=mylist[:] #this used to assign all elements to a so u have ur mylist safe
b=[]
b.append(a[0]) #this appends the first list in the list
del a[0] #now deleting appended list
while len(a)>0:
for val,i in enumerate(a):# enumerte gives index and value of list
if len(set(b[len(b)-1]).intersection(set(i)))==0: # this checks intersection so that both list should not have same elements
b.append(a[val])
del a[val]
print b
#output [['A', 'B'], ['C', 'D'], ['E', 'F'], ['A', 'C'], ['B', 'D'], ['C', 'E'], ['D', 'F'], ['A', 'E'], ['B', 'C'], ['D', 'E'], ['A', 'F'], ['B', 'E'], ['C', 'F'], ['A', 'D'], ['B', 'F']]
Using the neighborhood generator from this answer you can get the previous, current and next element in your loop, so that you can compare them. Then you can do something like this
from itertools import combinations
# Credit to Markus Jarderot for this function
def neighborhood(iterable):
iterator = iter(iterable)
prev = None
item = iterator.next() # throws StopIteration if empty.
for next in iterator:
yield (prev,item,next)
prev = item
item = next
# this can be written like this also prev,item=item,next
yield (prev,item,None)
data = ['A', 'B', 'C', 'D', 'E', 'F'];
comb = combinations(data, 2);
d = [];
for prev, item, next in neighborhood(comb):
# If prev and item both exist and neither are in the last element in d
if prev and item and not any(x in d[-1] for x in item):
d.append([item[0], item[1]])
elif item and not prev: # For the first element
d.append([item[0], item[1]])
print d
This prints
[['A', 'B'],
['C', 'D'],
['E', 'F']]
I'm aware this is probably not 100% what you need, but it should be able to get you where you want

Categories

Resources