tags:

views:

134

answers:

5

What is the simplest way to create this list in Python?

First, suppose I have this nested list:

oldList = [ [{'letter':'a'}], [{'letter':'b'}], [{'letter':'c'}] ]

I want a function to spit out:

newList = [ {'letter':a}, {'letter':'b'}, {'letter':'c'} ]

Well, this could be done manually. However, what if there are three nested? ...X nested

Tricky? :)

+2  A: 

http://www.daniel-lemire.com/blog/archives/2006/05/10/flattening-lists-in-python/

from that link (with a couple minor changes:

def flatten(l):
  if isinstance(l, list):
     return sum(map(flatten,l),[])
  else:
     return [l]
Jimmy
Way too broad: a dict also has an `__iter__`, for example, yet the OP's example makes it totally clear that he does NOT want to "flatten" dicts, only lists!
Alex Martelli
:) good point. that was an unnecessary edit by me from the original. (the other edit being the second parameter on sum)
Jimmy
A side note: PEP 8 encourages not to use lowercase L as an identifier. This makes the code less legible, because `l` (L) looks like `1` (one).
EOL
A: 

The Python Cookbook Martelli, Ravenscroft and Asher 2005 O'Reilley also offers a solution to this flattening problem.
See 4.6 Flattening a nested sequence.
This solution uses generators which can be a good thing if the lists are long.
Also, this solution deals equaly well with lists or tuples.

Note: Oops... I rushed a bit. I'm unsure of the legality of reproducing this snippet here... let me look for policy / precedents in this area.

Edit: later found reference as a Google Books preview.

Here's a link to this section of the book in Google books

mjv
As a co-author of that recipe (yep, Luther Blissett, c'est moi!-), I know think the last, most advanced, recursion-removal recipe is a tad too fancy -- the version I wrote (from scratch, no copying) in my answer above is slightly less optimized (does a bit more pop/append pairs than strictly needed... but they're cheap operations!), but, IMHO, easier to follow (no `else` branches, while the printed version has two;-).
Alex Martelli
Good to meet you Luther :-)
mjv
+4  A: 

Recursive solutions are simplest, but limited to at most a few thousand levels of nesting before you get an exception about too-deep recursion. For real generality, you can eliminate recursion by keeping your own stack; iterators are good things to keep on said stack, and the whole function's best written as a generator (just call list(flatten(thelist)) if you really want a huge list result).

def flatten(alist):
  stack = [iter(alist)]
  while stack:
    current = stack.pop()
    for item in current:
      if isinstance(item, list):
        stack.append(current)
        stack.append(iter(item))
        break
      yield item

Now this should let you handle as many levels of nesting as you have virtual memory for;-).

Alex Martelli
you can also increase the recursion limit with sys.setrecursionlimit
gnibbler
@Alex: glad to see you here. Sorry for a bit of meta, here, is my response re. copyrights etc? (BTW great non-recursive sol')
mjv
@gnibbler, only up to a limit, NOT without bounds. @mjv, by posting a link to a google books snippet you're most certainly in the clear (not sure how O'Reilly feels about republication in other public fora such as this one).
Alex Martelli
@Alex M Thanks for the hint. Hopefully the publisher would see it as free advertisement. 'nough on this, back to coding...
mjv
A: 

I prefer Alex Martelli's post as usual. Just want to add a not recommended trick:

from Tkinter import _flatten
print _flatten(oldList)
sunqiang
+1  A: 

The simplest answer is this

Only you can prevent nested lists

Do not create a list of lists using append. Create a flat list using extend.

S.Lott