Skip to content

Instantly share code, notes, and snippets.

@nikvdp
Created October 30, 2020 06:08
Show Gist options
  • Save nikvdp/e2a87f20680b1b1ecc8084885b15e396 to your computer and use it in GitHub Desktop.
Save nikvdp/e2a87f20680b1b1ecc8084885b15e396 to your computer and use it in GitHub Desktop.
A one liner to unwrap a list (or any iterable) with any amount of nesting
"""
A handy and cool recursive lambda (!) to safely get an item out of a deeply
nested list or iterable:
>>> unwrap = lambda x: unwrap(next(iter(x), None)) if '__iter__' in dir(x) and not isinstance(x, str) else x
>>> unwrap(2)
2
>>> unwrap(["hi"])
'hi'
>>> unwrap([[[[[[["ok ok, i get it"]]]]]]])
'ok ok, i get it'
see below for how it works
"""
# as an actual one-liner
unwrap = lambda x: unwrap(next(iter(x), None)) if '__iter__' in dir(x) and not isinstance(x, str) else x
# formatted over two lines to keep it less than 80 chrs
unwrap = lambda x: unwrap(next(iter(x), None)) \
if '__iter__' in dir(x) and not isinstance(x, str) else x
# in a more readable form
unwrap = (
lambda x: unwrap(next(iter(x), None))
if "__iter__" in dir(x) and not isinstance(x, str)
else x
)
# an shorter but unsafe variant that you can use if you are absolutely sure
# that the content does not contain any strings. if it receives a string it
# will cause a recursion depth exceeded exception)
unwrap = lambda x: unwrap(next(iter(x), None)) if '__iter__' in dir(x) else x
"""
How it works:
It uses `dir()` to check if `x` has an `__iter__()` method. If it does, this
means it's iterable, and we can use the `next()` function to ask it to give us
the next iteration. The second parameter (`, None`) to `next()` makes `next()`
return `None` instead of throwing an exception if there are no more items to
iterate over.
However, strings behave oddly in python, and have an `__iter__()` method even
though they are not actually iterable. So we use `not isinstance(x, str)` to
make sure that the item isn't a string.
Caveats and limitations:
If you're trying to unrwap something that's *actually* iteratable (for
example if you tried `unwrap([[[2,3]]])`) you will only get the first
result back (2).
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment