Joint nested list in Python - 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])

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

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.

Python - finding all possible grouping of elements in a list

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

Sorting a 2D list alphabetically?

I have a 2D list such as this:
lst = [['c', 'd', 'b'], ['d', 'c', 'a'], ['b', 'a', 'c']]
I would first like to sort each list within the list alphabetically like this:
lst = [['b', 'c', 'd'], ['a', 'c', 'd'], ['a', 'b', 'c']]
And finally, I would like to sort the whole list alphabetically which takes into account each element in a sublist:
lst = [['a', 'b', 'c'], ['a', 'c', 'd'], ['b', 'c', 'd']]
What would be the fastest way to achieve this? Thank you.
The fastest way in general should be just as you described it:
for sublist in lst:
sublist.sort()
lst.sort()
Alternatively, if you want to do it out of place:
new_lst = [sorted(sublist) for sublist in lst]
new_lst.sort()

Concatenate a list of lists excluding one index

Is there a Pythonic way for concatenating a list of lists, excluding an index of choice? For example, if I had
[['a'], ['b', 'c'], ['d'], ['e', 'f', 'g']]
and did not want index 1 in the result, my concatenated list would look like:
['a', 'd', 'e', 'f', 'g']
I could do this with a loop and checking against the iteration against my index of choice, but I'm hoping there's a cleaner way.
You can use slicing:
from itertools import chain
ls = [['a'], ['b', 'c'], ['d'], ['e', 'f', 'g']]
list(chain.from_iterable(ls[:1] + ls[2:]))
If you want to avoid the cost of adding the slices together and creating new lists, it gets a bit more complicated:
from itertools import chain, islice
list(chain.from_iterable(chain(islice(ls, 1), islice(ls, 2, None))))
Here is one way:
lists = [['a'], ['b', 'c'], ['d'], ['e', 'f', 'g']]
subset = [x for ind, x in enumerate(lists) if ind != 1]
subset # [['a'], ['d'], ['e', 'f', 'g']]
flattened = [item for l in subset for item in l]
flattened # ['a', 'd', 'e', 'f', 'g']
You could combine these into a single comprehension, I did it in two steps here to show more clearly what each part does.
this is ~ "I could do this with a loop and checking against the iteration against my index of choice...."
but in a list comprehension, no libs
nix = 1
myls = [['a'], ['b', 'c'], ['d'], ['e', 'f', 'g']]
[e for ls in myls for e in ls if ls != myls[nix]]
Out[11]: ['a', 'd', 'e', 'f', 'g']
no need for enumerate either
another of the slice and flatten possibilities that reads nice
sum(myls[:nix] + myls[nix+1:],[])
but some have a problem with the use of sum that way https://mathieularose.com/how-not-to-flatten-a-list-of-lists-in-python/
If you don't mind using an external library I could offer remove and flatten from iteration_utilities1:
>>> from iteration_utilities import remove, flatten
>>> l = [['a'], ['b', 'c'], ['d'], ['e', 'f', 'g']]
>>> list(flatten(remove(l, 1)))
['a', 'd', 'e', 'f', 'g']
1 I'm the author of that library.

Categories

Resources