Merge sublist with each item of list
Question:
I have a list of lists and I need to join them together with each item of list. See example below:
my_list = [1, [2, 3], [4, 5]]
Expected result:
['1', '1.2', '1.3', '1.2.4', '1.2.5', '1.3.4', '1.3.5']
I tried to write the logic but one or other items are always missing.
Answers:
You can use the itertools.product function from the itertools module to generate all possible combinations of items from the lists, then use a list comprehension to join the items together using the desired format.
Here is an example of how you can use it:
import itertools
my_list = [1, [2, 3], [4, 5]]
combinations = list(itertools.product(*my_list))
result = [".".join(map(str, x)) for x in combinations]
print(result)
This will output:
['1.2.4', '1.2.5', '1.3.4', '1.3.5']
Note that this assumes that all of the elements of the list are lists, if you have integer or string mixed in your list, you need to convert them to string before joining them.
def join_lists(result, prefix, items):
if not items:
result.append('.'.join(map(str, prefix)))
else:
for i, item in enumerate(items[0]):
join_lists(result, prefix + [item], items[1:])
join_lists(result, prefix, items[1:])
my_list = [1, [2, 3], [4, 5]]
result = []
join_lists(result, [1], my_list)
print(result)
will produce:
Output: ['1', '1.2', '1.3', '1.2.4', '1.2.5', '1.3.4', '1.3.5']
You could do this:
import itertools
my_list = [1, [2, 3], [4, 5]]
# First convert each scalar into list
my_list = [[e] if not isinstance(e, list) else e for e in my_list]
# and then each element into str
my_list = [list(map(str, e)) for e in my_list]
# Then initialize a result list and keep extending with product of the result
# with the next element in my_list
t = my_list[0]
out = []
out.extend(t)
for lst in my_list[1:]:
t = list(map('.'.join, itertools.product(t, lst)))
out.extend(t)
print(out)
['1', '1.2', '1.3', '1.2.4', '1.2.5', '1.3.4', '1.3.5']
# for the input my_list = [[1,2],3,[4,5]]
my_list = [[1,2],3,[4,5]]
print(out)
['1', '2', '1.3', '2.3', '1.3.4', '1.3.5', '2.3.4', '2.3.5']
Using itertools.accumulate
:
from itertools import accumulate, product
# ensure sub-items are lists
def as_lst(x):
return x if isinstance(x, list) else [str(x)]
out = [str(e) for l in (accumulate(map(as_lst, my_list),
lambda *x: ['.'.join(map(str, y))
for y in product(*x)])
)
for e in as_lst(l)]
print(out)
Output:
['1', '1.2', '1.3', '1.2.4', '1.2.5', '1.3.4', '1.3.5']
Output for my_list=[[1,2],3,[4,5]]
:
['1', '2', '1.3', '2.3', '1.3.4', '1.3.5', '2.3.4', '2.3.5']
I have a list of lists and I need to join them together with each item of list. See example below:
my_list = [1, [2, 3], [4, 5]]
Expected result:
['1', '1.2', '1.3', '1.2.4', '1.2.5', '1.3.4', '1.3.5']
I tried to write the logic but one or other items are always missing.
You can use the itertools.product function from the itertools module to generate all possible combinations of items from the lists, then use a list comprehension to join the items together using the desired format.
Here is an example of how you can use it:
import itertools
my_list = [1, [2, 3], [4, 5]]
combinations = list(itertools.product(*my_list))
result = [".".join(map(str, x)) for x in combinations]
print(result)
This will output:
['1.2.4', '1.2.5', '1.3.4', '1.3.5']
Note that this assumes that all of the elements of the list are lists, if you have integer or string mixed in your list, you need to convert them to string before joining them.
def join_lists(result, prefix, items):
if not items:
result.append('.'.join(map(str, prefix)))
else:
for i, item in enumerate(items[0]):
join_lists(result, prefix + [item], items[1:])
join_lists(result, prefix, items[1:])
my_list = [1, [2, 3], [4, 5]]
result = []
join_lists(result, [1], my_list)
print(result)
will produce:
Output: ['1', '1.2', '1.3', '1.2.4', '1.2.5', '1.3.4', '1.3.5']
You could do this:
import itertools
my_list = [1, [2, 3], [4, 5]]
# First convert each scalar into list
my_list = [[e] if not isinstance(e, list) else e for e in my_list]
# and then each element into str
my_list = [list(map(str, e)) for e in my_list]
# Then initialize a result list and keep extending with product of the result
# with the next element in my_list
t = my_list[0]
out = []
out.extend(t)
for lst in my_list[1:]:
t = list(map('.'.join, itertools.product(t, lst)))
out.extend(t)
print(out)
['1', '1.2', '1.3', '1.2.4', '1.2.5', '1.3.4', '1.3.5']
# for the input my_list = [[1,2],3,[4,5]]
my_list = [[1,2],3,[4,5]]
print(out)
['1', '2', '1.3', '2.3', '1.3.4', '1.3.5', '2.3.4', '2.3.5']
Using itertools.accumulate
:
from itertools import accumulate, product
# ensure sub-items are lists
def as_lst(x):
return x if isinstance(x, list) else [str(x)]
out = [str(e) for l in (accumulate(map(as_lst, my_list),
lambda *x: ['.'.join(map(str, y))
for y in product(*x)])
)
for e in as_lst(l)]
print(out)
Output:
['1', '1.2', '1.3', '1.2.4', '1.2.5', '1.3.4', '1.3.5']
Output for my_list=[[1,2],3,[4,5]]
:
['1', '2', '1.3', '2.3', '1.3.4', '1.3.5', '2.3.4', '2.3.5']