-2

I try to ream a nested list by a generator in a recursive way. Here is my code:

def reaming(items):
  print(items)
  if items:
    if isinstance(items,list):
      a, *b = items
      if isinstance(a,list):
        reaming(a)
      else:
        yield a

      reaming(b)
  else:
      yield items


for i in reaming([1,2,3,[4,5,6]]):
  print(i)

I expected "1 2 3 4 5 6" will be returned. But I got only "1". Why?

kanpu
  • 251
  • 2
  • 10
  • You are not yielding when recursing - `for _ in reaming(b): yield _` – Paulo Scardine Jan 16 '18 at 02:07
  • Possible duplicate: https://stackoverflow.com/a/16312281/674039 – wim Jan 16 '18 at 02:07
  • 2
    Please [edit] your post and rewrite your title. The title should describe a problem or meaningful question in a way that will be useful to future readers here seeing it in a list of search results. Your current title has absoutely nothing relevant or useful in it. While you're making that edit, put some effort into writing a better problem description and asking a more specific question than *Why?*. See [ask]. – Ken White Jan 16 '18 at 02:09
  • Also see https://stackoverflow.com/questions/2158395/flatten-an-irregular-list-of-lists – PM 2Ring Jan 16 '18 at 02:49

3 Answers3

2

reaming(a) or reaming(b) just return a generator, you need yield from:

def reaming(items):
  if items:
    if isinstance(items,list):
      a, *b = items
      if isinstance(a,list):
        yield from reaming(a)
      else:
        yield a

      yield from reaming(b)

test:

for i in reaming([1,2,3,[4,5,6]]):
  print(i)

#output
1
2
3
4
5
6
Sraw
  • 18,892
  • 11
  • 54
  • 87
0

As others have mentioned your generator needs to yield from the recursive calls.

But you are making this more complicated than it needs to be. Here's a reduced version of your code that will work on arbitrarily nested lists.

def reaming(items):
    for a in items:
        if isinstance(a, list):
            yield from reaming(a)
        else:
            yield a

for i in reaming([1, 2, [3, [4, [5], 6]]]):
    print(i)

output

1
2
3
4
5
6
PM 2Ring
  • 54,345
  • 6
  • 82
  • 182
0

The following would also work to flatten the list:

def reaming(items):
  new = []
  def inner(x):
    if isinstance(x, list):
      for y in x:
        inner(y)
    else:
      new.append(x)
  inner(items)
  return new

items = [1,2,3,[4,5,6]]

print(reaming(items))

#output

[1, 2, 3, 4, 5, 6]

For each element in items, check if the element is a list. If not, add it to a new list, new, which is returned by the function. If the element is a list, check each item within that list, etc.

kjmerf
  • 4,275
  • 3
  • 21
  • 29