<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>
<channel>
	<title>Comments on: Flattening lists in Python</title>
	<atom:link href="http://www.daniel-lemire.com/blog/archives/2006/05/10/flattening-lists-in-python/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.daniel-lemire.com/blog/archives/2006/05/10/flattening-lists-in-python/</link>
	<description>Daniel Lemire's blog is about life in academia, research in Computer Science, wondering how we can reconcile fast databases and algorithms with the informal and asemantic nature of the world around us. It is broadcasted from  Montreal (Canada).</description>
	<pubDate>Sun, 07 Sep 2008 04:00:20 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.1</generator>
		<item>
		<title>By: Bob the Chef</title>
		<link>http://www.daniel-lemire.com/blog/archives/2006/05/10/flattening-lists-in-python/#comment-49913</link>
		<dc:creator>Bob the Chef</dc:creator>
		<pubDate>Thu, 15 May 2008 21:35:46 +0000</pubDate>
		<guid isPermaLink="false">http://www.daniel-lemire.com/blog/?p=676#comment-49913</guid>
		<description>There is a problem with most of these in that they're recursive. Why is it a problem? Because python's stack is going to blow up when the depth of the list is something ridiculously large. 

So, we must do this with iteration. One way is to iterate over the list until no lists remain:

def flatten(lst):
    has_lists = True
    while has_lists:
        tmp_lst = []
        has_lists = False
        for elt in lst:
            if isinstance(elt, list):
                tmp_lst += elt
                has_lists = True
            else:
                tmp_lst.append(elt)
        lst = tmp_lst
    return lst

Of course, you're doing more iteration that you need to if the list contains elements of variable list depth. But since function calls are expensive in Python, it may actually be faster than recursion.</description>
		<content:encoded><![CDATA[<p>There is a problem with most of these in that they&#8217;re recursive. Why is it a problem? Because python&#8217;s stack is going to blow up when the depth of the list is something ridiculously large. </p>
<p>So, we must do this with iteration. One way is to iterate over the list until no lists remain:</p>
<p>def flatten(lst):<br />
    has_lists = True<br />
    while has_lists:<br />
        tmp_lst = []<br />
        has_lists = False<br />
        for elt in lst:<br />
            if isinstance(elt, list):<br />
                tmp_lst += elt<br />
                has_lists = True<br />
            else:<br />
                tmp_lst.append(elt)<br />
        lst = tmp_lst<br />
    return lst</p>
<p>Of course, you&#8217;re doing more iteration that you need to if the list contains elements of variable list depth. But since function calls are expensive in Python, it may actually be faster than recursion.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Markus</title>
		<link>http://www.daniel-lemire.com/blog/archives/2006/05/10/flattening-lists-in-python/#comment-49763</link>
		<dc:creator>Markus</dc:creator>
		<pubDate>Wed, 05 Mar 2008 16:29:46 +0000</pubDate>
		<guid isPermaLink="false">http://www.daniel-lemire.com/blog/?p=676#comment-49763</guid>
		<description>What about using the reduce-function?

E.g. 

def flatten(l):
   return reduce(operator.add, l)

Obviously this requires the operator-module import.</description>
		<content:encoded><![CDATA[<p>What about using the reduce-function?</p>
<p>E.g. </p>
<p>def flatten(l):<br />
   return reduce(operator.add, l)</p>
<p>Obviously this requires the operator-module import.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: timv</title>
		<link>http://www.daniel-lemire.com/blog/archives/2006/05/10/flattening-lists-in-python/#comment-49750</link>
		<dc:creator>timv</dc:creator>
		<pubDate>Sat, 01 Mar 2008 02:59:04 +0000</pubDate>
		<guid isPermaLink="false">http://www.daniel-lemire.com/blog/?p=676#comment-49750</guid>
		<description>A modified version of sweavo's post (which didn't work for me either):

def flatten(l):
  if isinstance(l,list):
    return sum(map(flatten,l),[])
  else:
    return [l]</description>
		<content:encoded><![CDATA[<p>A modified version of sweavo&#8217;s post (which didn&#8217;t work for me either):</p>
<p>def flatten(l):<br />
  if isinstance(l,list):<br />
    return sum(map(flatten,l),[])<br />
  else:<br />
    return [l]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: BioStatMatt</title>
		<link>http://www.daniel-lemire.com/blog/archives/2006/05/10/flattening-lists-in-python/#comment-49722</link>
		<dc:creator>BioStatMatt</dc:creator>
		<pubDate>Thu, 31 Jan 2008 22:10:32 +0000</pubDate>
		<guid isPermaLink="false">http://www.daniel-lemire.com/blog/?p=676#comment-49722</guid>
		<description>Sorry, my previous post didn't work either. But this one does. Honest.

def flatten(x):
 ans = []
 for i in range(len(x)):
  if isinstance(x[i],list):
   ans.extend(flatten(x[i]))
  else:
   ans.append(x[i])
 return ans</description>
		<content:encoded><![CDATA[<p>Sorry, my previous post didn&#8217;t work either. But this one does. Honest.</p>
<p>def flatten(x):<br />
 ans = []<br />
 for i in range(len(x)):<br />
  if isinstance(x[i],list):<br />
   ans.extend(flatten(x[i]))<br />
  else:<br />
   ans.append(x[i])<br />
 return ans</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: BioStatMatt</title>
		<link>http://www.daniel-lemire.com/blog/archives/2006/05/10/flattening-lists-in-python/#comment-49721</link>
		<dc:creator>BioStatMatt</dc:creator>
		<pubDate>Thu, 31 Jan 2008 21:57:09 +0000</pubDate>
		<guid isPermaLink="false">http://www.daniel-lemire.com/blog/?p=676#comment-49721</guid>
		<description>As far as I can tell, several of the functions presented above do not work, including sweavo's. Thie function below does work.

def flatten(x):
 ans = []
 for i in range(len(x)):
  if isinstance(x[i],list):
   ans = x[:i]+flatten(x[i])+x[i+1:]
  else:
   ans.append(x[i])
 return ans</description>
		<content:encoded><![CDATA[<p>As far as I can tell, several of the functions presented above do not work, including sweavo&#8217;s. Thie function below does work.</p>
<p>def flatten(x):<br />
 ans = []<br />
 for i in range(len(x)):<br />
  if isinstance(x[i],list):<br />
   ans = x[:i]+flatten(x[i])+x[i+1:]<br />
  else:<br />
   ans.append(x[i])<br />
 return ans</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: anon</title>
		<link>http://www.daniel-lemire.com/blog/archives/2006/05/10/flattening-lists-in-python/#comment-49631</link>
		<dc:creator>anon</dc:creator>
		<pubDate>Fri, 14 Dec 2007 13:23:28 +0000</pubDate>
		<guid isPermaLink="false">http://www.daniel-lemire.com/blog/?p=676#comment-49631</guid>
		<description>def flatten(x):
    result = []
    for v in x:
        if hasattr(v, '__iter__') and not isinstance(v, basestring):
            result.extend(flatten(v))
        else:
            result.append(v)
    return result</description>
		<content:encoded><![CDATA[<p>def flatten(x):<br />
    result = []<br />
    for v in x:<br />
        if hasattr(v, &#8216;__iter__&#8217;) and not isinstance(v, basestring):<br />
            result.extend(flatten(v))<br />
        else:<br />
            result.append(v)<br />
    return result</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: sweavo</title>
		<link>http://www.daniel-lemire.com/blog/archives/2006/05/10/flattening-lists-in-python/#comment-49393</link>
		<dc:creator>sweavo</dc:creator>
		<pubDate>Wed, 11 Jul 2007 16:45:09 +0000</pubDate>
		<guid isPermaLink="false">http://www.daniel-lemire.com/blog/?p=676#comment-49393</guid>
		<description>def flatten(l):
  if isinstance(l,list):
    return sum(map(flatten,l))
  else:
    return l</description>
		<content:encoded><![CDATA[<p>def flatten(l):<br />
  if isinstance(l,list):<br />
    return sum(map(flatten,l))<br />
  else:<br />
    return l</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jordan Callicoat</title>
		<link>http://www.daniel-lemire.com/blog/archives/2006/05/10/flattening-lists-in-python/#comment-26981</link>
		<dc:creator>Jordan Callicoat</dc:creator>
		<pubDate>Mon, 04 Sep 2006 07:33:40 +0000</pubDate>
		<guid isPermaLink="false">http://www.daniel-lemire.com/blog/?p=676#comment-26981</guid>
		<description>Here is a version from the &lt;a href="http://aspn.activestate.com/ASPN/Mail/Message/python-list/453883" rel="nofollow"&gt;mailing list&lt;/a&gt;:

&lt;code&gt;def flatten(seq):
  res = []
  for item in seq:
    if (isinstance(item, (tuple, list))):
      res.extend(flatten(item))
    else:
      res.append(item)
  return res&lt;/code&gt;

Another version is listed a in recipe &lt;a href="http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/363051" rel="nofollow"&gt;363051&lt;/a&gt;:

&lt;code&gt;import sys
def flatten(inlist, ltype=(list,tuple), maxint=sys.maxint):
  try:
    for ind in xrange(maxint):
      while isinstance(inlist[ind], ltype):
        inlist[ind:ind+1] = list(inlist[ind])
  except IndexError:
    pass
  return inlist&lt;/code&gt;</description>
		<content:encoded><![CDATA[<p>Here is a version from the <a href="http://aspn.activestate.com/ASPN/Mail/Message/python-list/453883" rel="nofollow">mailing list</a>:</p>
<p><code>def flatten(seq):<br />
  res = []<br />
  for item in seq:<br />
    if (isinstance(item, (tuple, list))):<br />
      res.extend(flatten(item))<br />
    else:<br />
      res.append(item)<br />
  return res</code></p>
<p>Another version is listed a in recipe <a href="http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/363051" rel="nofollow">363051</a>:</p>
<p><code>import sys<br />
def flatten(inlist, ltype=(list,tuple), maxint=sys.maxint):<br />
  try:<br />
    for ind in xrange(maxint):<br />
      while isinstance(inlist[ind], ltype):<br />
        inlist[ind:ind+1] = list(inlist[ind])<br />
  except IndexError:<br />
    pass<br />
  return inlist</code></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Hans Meine</title>
		<link>http://www.daniel-lemire.com/blog/archives/2006/05/10/flattening-lists-in-python/#comment-7211</link>
		<dc:creator>Hans Meine</dc:creator>
		<pubDate>Thu, 01 Jun 2006 17:20:47 +0000</pubDate>
		<guid isPermaLink="false">http://www.daniel-lemire.com/blog/?p=676#comment-7211</guid>
		<description>No, Daniel, I don't know a better way ATM.
A possible reason for this obvious lack could be that the Python community likes to have functions with clear semantics.  For example, sometimes I want to flatten only one level, or different types, for example, given this input:

[[[1,2,3], (42,None)], [4,5], [6], 7, MyVector(8,9,10)]

One could imagine the following outputs:

# flattened one level:
[[1, 2, 3], (42, None), 4, 5, 6, 7, MyVector(8,9,10)]

# flattened all lists:
[1, 2, 3, (42, None), 4, 5, 6, 7, MyVector(8,9,10)]

# flattened all lists and tuples:
[1, 2, 3, 42, None, 4, 5, 6, 7, MyVector(8,9,10)]

# flattened all iterables:
[1, 2, 3, 42, None, 4, 5, 6, 7, 8, 9, 10]

@Will: Daniels version looks more optimized to me.  The question whether isinstance is better than checking the class is another possible implementation decision, e.g. given the following definition of MyVector:

class MyVector(list):
     def __init__(self, *args):
         list.__init__(self, args)

Your version would handle it the same as a list, while daniels would not flatten it.

For the record, the above corresponds to the following checks in Daniel's flatten function:
  if i.__class__ is list:
  if i.__class__ in (list, tuple):
  if isinstance(i, list):
  if isinstance(i, (list, tuple)):
  if hasattr(i, "__iter__"):
AFAICS the simplest way to flatten only one layer is to change the recursive call to "list" instead of "flatten".</description>
		<content:encoded><![CDATA[<p>No, Daniel, I don&#8217;t know a better way ATM.<br />
A possible reason for this obvious lack could be that the Python community likes to have functions with clear semantics.  For example, sometimes I want to flatten only one level, or different types, for example, given this input:</p>
<p>[[[1,2,3], (42,None)], [4,5], [6], 7, MyVector(8,9,10)]</p>
<p>One could imagine the following outputs:</p>
<p># flattened one level:<br />
[[1, 2, 3], (42, None), 4, 5, 6, 7, MyVector(8,9,10)]</p>
<p># flattened all lists:<br />
[1, 2, 3, (42, None), 4, 5, 6, 7, MyVector(8,9,10)]</p>
<p># flattened all lists and tuples:<br />
[1, 2, 3, 42, None, 4, 5, 6, 7, MyVector(8,9,10)]</p>
<p># flattened all iterables:<br />
[1, 2, 3, 42, None, 4, 5, 6, 7, 8, 9, 10]</p>
<p>@Will: Daniels version looks more optimized to me.  The question whether isinstance is better than checking the class is another possible implementation decision, e.g. given the following definition of MyVector:</p>
<p>class MyVector(list):<br />
     def __init__(self, *args):<br />
         list.__init__(self, args)</p>
<p>Your version would handle it the same as a list, while daniels would not flatten it.</p>
<p>For the record, the above corresponds to the following checks in Daniel&#8217;s flatten function:<br />
  if i.__class__ is list:<br />
  if i.__class__ in (list, tuple):<br />
  if isinstance(i, list):<br />
  if isinstance(i, (list, tuple)):<br />
  if hasattr(i, &#8220;__iter__&#8221;):<br />
AFAICS the simplest way to flatten only one layer is to change the recursive call to &#8220;list&#8221; instead of &#8220;flatten&#8221;.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Will</title>
		<link>http://www.daniel-lemire.com/blog/archives/2006/05/10/flattening-lists-in-python/#comment-5055</link>
		<dc:creator>Will</dc:creator>
		<pubDate>Wed, 10 May 2006 23:20:34 +0000</pubDate>
		<guid isPermaLink="false">http://www.daniel-lemire.com/blog/?p=676#comment-5055</guid>
		<description>I think you just want isinstance, but here's a nice recursive function:

How about:

def flatten(x):
    if not isinstance(x,list):
	return x
    elif len(x) is 0:
	return []
    elif isinstance(x[0],list):
	return flatten(x[0]) + flatten(x[1:])
    else:
	return [x[0]] + flatten(x[1:])</description>
		<content:encoded><![CDATA[<p>I think you just want isinstance, but here&#8217;s a nice recursive function:</p>
<p>How about:</p>
<p>def flatten(x):<br />
    if not isinstance(x,list):<br />
	return x<br />
    elif len(x) is 0:<br />
	return []<br />
    elif isinstance(x[0],list):<br />
	return flatten(x[0]) + flatten(x[1:])<br />
    else:<br />
	return [x[0]] + flatten(x[1:])</p>
]]></content:encoded>
	</item>
</channel>
</rss>
