Given the case I have the following List:
['graph_edges', ['graph_nodes'], ['graph_nodes'], ['graph_edges2', ['graph_nodes2'], ['graph_nodes2']]]
And I wish to convert it to something like:
['graph_edges', 'graph_nodes', 'graph_nodes', 'graph_edges2', 'graph_nodes2', 'graph_nodes2']
# I would list(set(thislist)) afterwards
There is a ton of solutions out there already but strangely for my case I can't get anything meaningful done:
from functools import reduce
import operator
reduce(operator.concat,['graph_edges', ['graph_nodes'], ['graph_nodes'], ['graph_edges2', ['graph_nodes2'], ['graph_nodes2']]])
*** TypeError: can only concatenate str (not "list") to str
Same with sum
:
sum(['graph_edges', ['graph_nodes'], ['graph_nodes'], ['graph_edges2', ['graph_nodes2'], ['graph_nodes2']]], [])
This one-liner unwraps too much:
> [item for sublist in ['graph_edges', ['graph_nodes'], ['graph_nodes'], ['graph_edges2', ['graph_nodes2'], ['graph_nodes2']]] for item in sublist]
['g', 'r', 'a', 'p', 'h', '_', 'e', 'd', 'g', 'e', 's', 'graph_nodes', 'graph_nodes', 'graph_edges2', ['graph_nodes2'], ['graph_nodes2']]
Or with itertools:
>!list(itertools.chain(*lol))
['g', 'r', 'a', 'p', 'h', '_', 'e', 'd', 'g', 'e', 's', 'graph_nodes', 'graph_nodes', 'graph_edges2', ['graph_nodes2'], ['graph_nodes2']]
Disclaimer: I tried these in ipdb
, so there's always a chance of a bug
My current (not working) and very unsatisfying solution is this here:
retlist= []
dedefined=['graph_edges', ['graph_nodes'], ['graph_nodes'], ['graph_edges2', ['graph_nodes2'], ['graph_nodes2']]]
for element in dedefined:
if isinstance(element,list):
retlist =self.getSingleElement(element)
else:
retlist.append(element)
return list(set(retlist))
@classmethod
def getSingleElement(cls,element):
if isinstance(element,list):
return cls.getSingleElement(*element)
else: return element
When element
reaches ['graph_edges2', ['graph_nodes2'], ['graph_nodes2']]
it's failing, but I won't be able to think of something meaningful. I could either make a generator that yields new values instead of returns or iterate through every element and make it a list which can be dissolved. But none of these ideas are convincing to me
CodePudding user response:
def flatten(array):
flat = []
for member in array:
if isinstance(member, (tuple, list)):
flat.extend(flatten(member))
else:
flat.append(member)
return flat
CodePudding user response:
You need to use recursion to account for the fact that the lists can be nested arbitrarily deep:
def flatten(lst):
result = []
for item in lst:
# You can use:
# if not isinstance(item, list):
# if you have other items besides integers in your nested list.
if isinstance(item, str):
result.append(item)
else:
result.extend(flatten(item))
return result
This outputs:
['graph_edges', 'graph_nodes', 'graph_nodes',
'graph_edges2', 'graph_nodes2', 'graph_nodes2']