A
For starters, this is the version that uses branches and cycles to make clear the expected behaviour:from collections import Iterable
def flatten_gen(nested, isatom=lambda x: not isinstance(x, Iterable)):
for item in nested:
if isatom(item):
yield item
else:
yield from flatten_gen(item)
Example:lst = [1, [2, 3], 4, [[6, 7]]]
print(list(flatten_gen(lst)))
-> [1, 2, 3, 4, 6, 7]
where isatom() The predicament determines what is an atom (indivisible object) in terms of this method. It's supposed that "not atoms" can be transferred to the cycle to get the objects they're made of.Algorithm is straight-line: by selecting the elements of the transferred list, giving the atoms as they are, and for composite objects, we call the generator recurring.Since default lines work with cycles, if you want to treat them as atoms in your case, then tell them isatom Clearly:isatom = lambda x: isinstance(x, str) or not instance(x, Iterable)
If whole numbers are considered to be atoms, isatom = lambda x: isinstance(x, int)♪Recurring version without express injection, cycles using https://www.python.org/dev/peps/pep-3132/#rationale :def flatten(nested):
try:
first, *rest = nested
except TypeError: # not an iterable
return [nested]
except ValueError: # empty
return []
return flatten(first) + flatten(rest)
The code deflects the first element from the attached list and connects the flat list derived from it by a recurring challenge. flatten(first)with a flat list received with the remaining entry list flatten(rest)♪If the first element cannot be deactivated because the entry of an empty or scallar dan (not listed, for example), the empty list or that scallar inside the list is returned accordingly.If, at the inlet, the list with numbers is reduced, at each level, until the function is summed up with simple parameters: number or empty list, which results in the return of specific values and the collection of the final result when the challenge is raised.This implementation does not work without adaptation, as 'a' == 'a'[0] (a line of one symbol is equal to its first symbol) which leads to an endless recurrence in this case. The code is not optimized by productivity (for simplicity), but not if/else branches and cycles.This is a similar, but more effective version that uses the generator:def flatten_gen(nested):
try:
it = iter(nested)
except TypeError: # not an iterable
yield nested
return
try:
first = next(it)
except StopIteration: # empty
return
yield from flatten_gen(first)
yield from flatten_gen(it)
The generator is trying to get the terator. it by iter(nested) and if a scallar (e.g. number) is emitted at the entrance TypeError and the generator is returning this scallar.yield) next(it) returns the first element from the heterator if it's not empty. Scanners for the first element and the remaining elements in the section are then recurring it Iterator.If you can use library code cycles, like sum(map(flatten, lst, [])) of https://ru.stackoverflow.com/a/584610/23044 You can improve. flatten_gen() Generator using https://docs.python.org/3/library/itertools.html#itertools.chain :from itertools import chain
def flatten_gen(nested):
try:
it = iter(nested)
except TypeError: # not an iterable
yield nested
else:
yield from chain.from_iterable(map(flatten_gen, it))
Since the competition is not used in this case to achieve the cycle, the number of challenges is twice as low.If you want to, you can write in one word:def flatten(nested):
return (isinstance(nested, int) and [nested] # an int
or nested # empty
and flatten(nested[0]) + flatten(nested[1:])) # non-empty list
What works, thanks to short-circuit behavior and/or logical operators. It is not clear whether this is a use of the branch.If nested It's an entire code that returns this number to the list.[nested]) If nested Not a whole number (a list), he returns immediately if it's empty (len(nested) == 0 Which means bool(nested) is False) If nested not an empty list, the merging of the flat lists, returned by the competing calls for the first element and the rest of the list, is being returned, as in the decisions above.If we move further towards the inadvertentity of the code, the reset can be replaced by indexing the lists and lambdato delay implementation:def flatten(nested):
return [
lambda: [ # list (not an int)
lambda: flatten(nested[0]) + flatten(nested[1:]), # non-empty list
lambda: [] # empty
]not nested,
lambda: [nested] # an int
]isinstance(nested, int)
General idea: True == 1 and False == 0 Pitton, so the expression [on_false, on_true]condition Call. on_false function if condition and false on_trueIf it's true.