Python - finding all possible grouping of elements in a list - python

I am trying to find a nice Pythonic way for finding all possible combinations of splitting a list into two groups, as in the following example:
my_array = [A,B,C]
The output should be:
[[[A],[B]]
[[A],[B,C]]
[[A],[C]]
[[A,B],[C]]
[[A,C],[B]]
[[B],[A]]
[[B],[A,C]]
[[B],[C]]
[[B,C],[A]]
[[C],[A]]
[[C],[A,B]]
[[C],[B]]]
Thanks!

Maybe this is what you need:
import itertools
my_array = ['A','B','C']
combos = []
for i in range(1,len(my_array)):
combos += itertools.combinations(my_array, i)
result = []
for c1 in combos:
curr = list(c1)
for c2 in combos:
if not any(i in curr for i in c2):
result.append([curr, list(c2)])
result
#[[['A'], ['B']],
# [['A'], ['C']],
# [['A'], ['B', 'C']],
# [['B'], ['A']],
# [['B'], ['C']],
# [['B'], ['A', 'C']],
# [['C'], ['A']],
# [['C'], ['B']],
# [['C'], ['A', 'B']],
# [['A', 'B'], ['C']],
# [['A', 'C'], ['B']],
# [['B', 'C'], ['A']]]

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']]
>>>

Create a list only considering the elements of another list

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']]

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))

Combining elements in a list of list based on having common elements

I have a list of lists like so
list=[[a], [b], [c], [d],[e],[f], [a,f], [b,c], [c,e], [b, d,f]]
note that it includes singles and combinations.
What I would like to do is to iterate the list so that a new list of every possible combination of these sub-components is appended to the list of lists if and only if they share at least one common entry.
so the product is as follows
list2=[[a], [b], [c], [d],[e],[f], [a,f], [b,c], [c,e], [b, d,f], **[b,c,e], [a,b,d,f], [b,c,d,f], [b,c,d,e,f], [a,b,c,d,e,f]]**
Note the new part of the list contains the original list of lists
def similar(x):
prev_l = 0
while prev_l != len(x):
to_add = []
prev_l = len(x)
for i in x:
if len(i) == 1:
continue
for j in x:
if len(j) == 1:
continue
if any([_ in j for _ in i]) and not any([set(i+j) == set(_) for _ in x]) and not any([set(i+j) == set(_) for _ in to_add]) and i != j:
to_add.append(list(set(i+j)))
x += to_add
return x
Input:
>>> l = [['a'], ['b'], ['c'], ['d'],['e'],['f'], ['a','f'], ['b','c'], ['c','e'], ['b', 'd','f']]
>>> similar(l)
Output:
>>> l
[['a'], ['b'], ['c'], ['d'], ['e'], ['f'], ['a', 'f'], ['b', 'c'], ['c', 'e'], ['b', 'd', 'f'], ['b', 'a', 'd', 'f'], ['b', 'e', 'c'], ['b', 'd', 'c', 'f'], ['b', 'a', 'f', 'd', 'c'], ['b', 'f', 'e', 'd', 'c'], ['b', 'a', 'f', 'e', 'd', 'c']]
I should note this has O(n^3) in worst case. If you're using this for something floyd warshall I wouldn't be too worried as that has O(n^3) anyway, but if not you should definitely populate a distance matrix and then look for adjacency in that.

Joint nested list in Python

How to convert a nested list like below?
d = [[['a','b'], ['c']], [['d'], ['e', 'f']]]
-> [['a','b','c'], ['d','e','f']]
I found a similar question. But it's a little different.
join list of lists in python [duplicate]
Update
Mine is not smart
new = []
for elm in d:
tmp = []
for e in elm:
for ee in e:
tmp.append(ee)
new.append(tmp)
print(new)
[['a', 'b', 'c'], ['d', 'e', 'f']]
Lots of ways to do this, but one way is with chain
from itertools import chain
[list(chain(*x)) for x in d]
results in:
[['a', 'b', 'c'], ['d', 'e', 'f']]
sum(ls, []) to flatten a list has issues, but for short lists its just too concise to not mention
d = [[['a','b'], ['c']], [['d'], ['e', 'f']]]
[sum(ls, []) for ls in d]
Out[14]: [['a', 'b', 'c'], ['d', 'e', 'f']]
This is a simple solution for your question
new_d = []
for inner in d:
new_d.append([item for x in inner for item in x])

Categories

Resources