Home > Blockchain >  How can we convert an arbitrary iterable of iterables into a nested list of lists of strings?
How can we convert an arbitrary iterable of iterables into a nested list of lists of strings?

Time:01-16

Suppose obj has an __iter__() method.

We want to write a function which accepts obj as input and outputs a nested list of lists of lists .... of lists of strings.

If an object is iterable, and is not a string, we recur.

If an object is a string, we return the string.

If an object is non-iterable, we call the string-class constructor on that object, and return the resulting string.

Unfortunately, there may be self-loops. That is, an objects iter method might return an object we have seen previously.

root.__iter__().__next__().__next__().__iter__().__next__().__next__().__iter__().__next__() == root

Maybe we should use the id() function to check if the object has been seen previously?

CodePudding user response:

Try this:

from collections.abc import Iterable


def collect(obj):
    if isinstance(obj, Iterable) and not isinstance(obj, str):
        return list(map(collect, obj))
    else:
        return str(obj)


obj = iter([iter([iter(['a', 2]), 'cd']), iter(['ef', 'gh'])])
print(collect(obj))  # => [[['a', '2'], 'cd'], ['ef', 'gh']]

I think that the id() check is necessary because once an iterator is iterated through, all the elements will be exhausted and there won't be anything else to iterate through.

CodePudding user response:

This approach optimistically iterates any non-string t and recovers from errors using an exception handler -

def collect(t):
  try:
    if isinstance(t, str):
      return t
    else:
      return list(collect(v) for v in t)
  except TypeError:
    return t
  • Related