Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #51103 > unrolled thread

Converting a list of lists to a single list

Started bysteve@divillo.com
First post2013-07-23 14:52 -0700
Last post2013-07-24 11:11 -0700
Articles 9 — 7 participants

Back to article view | Back to comp.lang.python


Contents

  Converting a list of lists to a single list steve@divillo.com - 2013-07-23 14:52 -0700
    Re: Converting a list of lists to a single list Rafael Durán Castañeda <rafadurancastaneda@gmail.com> - 2013-07-24 00:34 +0200
    Re: Converting a list of lists to a single list MRAB <python@mrabarnett.plus.com> - 2013-07-23 23:52 +0100
    Re: Converting a list of lists to a single list Zero Piraeus <schesis@gmail.com> - 2013-07-23 18:49 -0400
    Re: Converting a list of lists to a single list Terry Reedy <tjreedy@udel.edu> - 2013-07-23 19:02 -0400
    Re: Converting a list of lists to a single list Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2013-07-23 20:28 -0400
    Re: Converting a list of lists to a single list Chris Angelico <rosuav@gmail.com> - 2013-07-24 15:40 +1000
    Re: Converting a list of lists to a single list Terry Reedy <tjreedy@udel.edu> - 2013-07-24 11:56 -0400
    Re: Converting a list of lists to a single list steve@divillo.com - 2013-07-24 11:11 -0700

#51103 — Converting a list of lists to a single list

Fromsteve@divillo.com
Date2013-07-23 14:52 -0700
SubjectConverting a list of lists to a single list
Message-ID<ee6f5c48-6cb1-498f-813a-be2eef5411fc@googlegroups.com>
I think that itertools may be able to do what I want but I have not been able to figure out how.

I want to convert an arbitrary number of lists with an arbitrary number of elements in each list into a single list as follows.

Say I have three lists:

[[A0,A1,A2], [B0,B1,B2] [C0,C1,C2]]

I would like to convert those to a single list that looks like this:

[A0,B0,C0,C1,C2,B1,C0,C1,C2,B2,C0,C1,C2,A1,B0,C0,C1,C2,B1,C0,C1,C2,B2,C0,C1,C2,A2,B0,C0,C1,C2,B1,C0,C1,C2,B2,C0,C1,C2]

An easier way to visualize the pattern I want is as a tree.

A0
	B0
		C0
		C1
		C2
	B1
		C0
		C1
		C2
	B2
		C0
		C1
		C2
A1
	B0
		C0
		C1
		C2
	B1
		C0
		C1
		C2
	B2
		C0
		C1
		C2
A2
	B0
		C0
		C1
		C2
	B1
		C0
		C1
		C2
	B2
		C0
		C1
		C2

[toc] | [next] | [standalone]


#51105

FromRafael Durán Castañeda <rafadurancastaneda@gmail.com>
Date2013-07-24 00:34 +0200
Message-ID<mailman.5015.1374618881.3114.python-list@python.org>
In reply to#51103
El 23/07/13 23:52, steve@divillo.com escribió:
> [[A0,A1,A2], [B0,B1,B2] [C0,C1,C2]]
Hi,

I think you are looking for itertools.chain, or in this case, 
itertools.chain.from_iterable:

In [1]: x = [['A0','A1','A2'], ['B0','B1','B2'], ['C0','C1','C2']]

In [2]: import itertools

In [3]: [ y for y in itertools.chain.from_iterable(x)]
Out[3]: ['A0', 'A1', 'A2', 'B0', 'B1', 'B2', 'C0', 'C1', 'C2']

HTH

[toc] | [prev] | [next] | [standalone]


#51107

FromMRAB <python@mrabarnett.plus.com>
Date2013-07-23 23:52 +0100
Message-ID<mailman.5017.1374619944.3114.python-list@python.org>
In reply to#51103
On 23/07/2013 22:52, steve@divillo.com wrote:
> I think that itertools may be able to do what I want but I have not been able to figure out how.
>
> I want to convert an arbitrary number of lists with an arbitrary number of elements in each list into a single list as follows.
>
> Say I have three lists:
>
> [[A0,A1,A2], [B0,B1,B2] [C0,C1,C2]]
>
> I would like to convert those to a single list that looks like this:
>
> [A0,B0,C0,C1,C2,B1,C0,C1,C2,B2,C0,C1,C2,A1,B0,C0,C1,C2,B1,C0,C1,C2,B2,C0,C1,C2,A2,B0,C0,C1,C2,B1,C0,C1,C2,B2,C0,C1,C2]
>
> An easier way to visualize the pattern I want is as a tree.
>
> A0
> 	B0
> 		C0
> 		C1
> 		C2
> 	B1
> 		C0
> 		C1
> 		C2
> 	B2
> 		C0
> 		C1
> 		C2
> A1
> 	B0
> 		C0
> 		C1
> 		C2
> 	B1
> 		C0
> 		C1
> 		C2
> 	B2
> 		C0
> 		C1
> 		C2
> A2
> 	B0
> 		C0
> 		C1
> 		C2
> 	B1
> 		C0
> 		C1
> 		C2
> 	B2
> 		C0
> 		C1
> 		C2
>
Using recursion:

def tree_list(items):
     if len(items) == 1:
         return items[0]

     sublist = tree_list(items[1 : ])

     result = []

     for item in items[0]:
         result.append(item)
         result.extend(sublist)

     return result

items = [["A0","A1","A2"], ["B0","B1","B2"], ["C0","C1","C2"]]
print(tree_list(items))

[toc] | [prev] | [next] | [standalone]


#51108

FromZero Piraeus <schesis@gmail.com>
Date2013-07-23 18:49 -0400
Message-ID<mailman.5018.1374620275.3114.python-list@python.org>
In reply to#51103
:

On 23 July 2013 17:52,  <steve@divillo.com> wrote:
>
> Say I have three lists:
>
> [[A0,A1,A2], [B0,B1,B2] [C0,C1,C2]]
>
> I would like to convert those to a single list that looks like this:
>
[A0,B0,C0,C1,C2,B1,C0,C1,C2,B2,C0,C1,C2,A1,B0,C0,C1,C2,B1,C0,C1,C2,B2,C0,C1,C2,A2,B0,C0,C1,C2,B1,C0,C1,C2,B2,C0,C1,C2]

How's this:

from itertools import chain

def treeify(seq):
    if seq:
        return list(chain(*([x] + treeify(seq[1:]) for x in seq[0])))
    else:
        return []

>>> treeify([['A0', 'A1', 'A2'], ['B0', 'B1', 'B2'], ['C0', 'C1', 'C2']])
['A0', 'B0', 'C0', 'C1', 'C2', 'B1', 'C0', 'C1', 'C2', 'B2', 'C0', 'C1', 'C2',
 'A1', 'B0', 'C0', 'C1', 'C2', 'B1', 'C0', 'C1', 'C2', 'B2', 'C0', 'C1', 'C2',
 'A2', 'B0', 'C0', 'C1', 'C2', 'B1', 'C0', 'C1', 'C2', 'B2', 'C0', 'C1', 'C2']

 -[]z.

[toc] | [prev] | [next] | [standalone]


#51109

FromTerry Reedy <tjreedy@udel.edu>
Date2013-07-23 19:02 -0400
Message-ID<mailman.5019.1374620579.3114.python-list@python.org>
In reply to#51103
On 7/23/2013 5:52 PM, steve@divillo.com wrote:
> I think that itertools may be able to do what I want but I have not
> been able to figure out how.

A recursive generator suffices.

> I want to convert an arbitrary number of lists with an arbitrary
> number of elements in each list into a single list as follows.
>
> Say I have three lists:
>
> [[A0,A1,A2], [B0,B1,B2] [C0,C1,C2]]
>
> I would like to convert those to a single list that looks like this:
>
> [A0,B0,C0,C1,C2,B1,C0,C1,C2,B2,C0,C1,C2,
 >  A1,B0,C0,C1,C2,B1,C0,C1,C2,B2,C0,C1,C2,
 >  A2,B0,C0,C1,C2,B1,C0,C1,C2,B2,C0,C1,C2]

def crossflat(lofl):
     if lofl:
         first = lofl.pop(0)
         for o in first:
            yield o
            yield from crossflat(lofl.copy())

A0, A1, A2 = 100, 101, 102
B0, B1, B2 = 10, 11, 12
C0, C1, C2 = 0, 1, 2
LL = [[A0, A1, A2], [B0, B1, B2], [C0, C1, C2]]
cfLL = list(crossflat(LL))
print(cfLL)
assert cfLL == [
    A0, B0, C0, C1, C2, B1, C0, C1, C2, B2, C0, C1, C2,
    A1, B0, C0, C1, C2, B1, C0, C1, C2, B2, C0, C1, C2,
    A2, B0, C0, C1, C2, B1, C0, C1, C2, B2, C0, C1, C2]

passes

-- 
Terry Jan Reedy

[toc] | [prev] | [next] | [standalone]


#51113

FromDennis Lee Bieber <wlfraed@ix.netcom.com>
Date2013-07-23 20:28 -0400
Message-ID<mailman.5023.1374625711.3114.python-list@python.org>
In reply to#51103
On Wed, 24 Jul 2013 00:34:31 +0200, Rafael Durán Castañeda
<rafadurancastaneda@gmail.com> declaimed the following:

>El 23/07/13 23:52, steve@divillo.com escribió:
>> [[A0,A1,A2], [B0,B1,B2] [C0,C1,C2]]
>Hi,
>
>I think you are looking for itertools.chain, or in this case, 
>itertools.chain.from_iterable:
>
>In [1]: x = [['A0','A1','A2'], ['B0','B1','B2'], ['C0','C1','C2']]
>
>In [2]: import itertools
>
>In [3]: [ y for y in itertools.chain.from_iterable(x)]
>Out[3]: ['A0', 'A1', 'A2', 'B0', 'B1', 'B2', 'C0', 'C1', 'C2']
>
	No, that just flattened the lists... The OP example shows the third
list is repeated after each element of the second list, and the flattened
result of that is then repeated for each element of the first list (and
flattened).
op> I would like to convert those to a single list that looks like this:
op> 
op>
[A0,B0,C0,C1,C2,B1,C0,C1,C2,B2,C0,C1,C2,A1,B0,C0,C1,C2,B1,C0,C1,C2,B2,C0,C1,C2,A2,B0,C0,C1,C2,B1,C0,C1,C2,B2,C0,C1,C2]
op> 

-=-=-=-=-=-

inp = [ ["%s%s" % (a,o) for o in "012"] for a in "ABC"]
print inp

def repFlatten(LoL):    #LoL List of Lists
    if not LoL or (type(LoL) != type([])
                   or type(LoL[0]) != type([])):
        return LoL
    res = []
    for itm in LoL[0]:
        res.append(itm)
        res.extend(repFlatten(LoL[1:]))
    return res

print repFlatten(inp)
-=-=-=-=-=-
[['A0', 'A1', 'A2'], ['B0', 'B1', 'B2'], ['C0', 'C1', 'C2']]

['A0', 'B0', 'C0', 'C1', 'C2', 'B1', 'C0', 'C1', 'C2', 'B2', 'C0', 'C1',
'C2', 'A1', 'B0', 'C0', 'C1', 'C2', 'B1', 'C0', 'C1', 'C2', 'B2', 'C0',
'C1', 'C2', 'A2', 'B0', 'C0', 'C1', 'C2', 'B1', 'C0', 'C1', 'C2', 'B2',
'C0', 'C1', 'C2']
-- 
	Wulfraed                 Dennis Lee Bieber         AF6VN
    wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/

[toc] | [prev] | [next] | [standalone]


#51118

FromChris Angelico <rosuav@gmail.com>
Date2013-07-24 15:40 +1000
Message-ID<mailman.5025.1374644439.3114.python-list@python.org>
In reply to#51103
On Wed, Jul 24, 2013 at 8:34 AM, Rafael Durán Castañeda
<rafadurancastaneda@gmail.com> wrote:
> In [3]: [ y for y in itertools.chain.from_iterable(x)]
> Out[3]: ['A0', 'A1', 'A2', 'B0', 'B1', 'B2', 'C0', 'C1', 'C2']

Complete aside, given that this has already been pointed out as
solving a different problem: Any time you see a list comp that just
does "[ x for x in foo ]", check to see if it can be replaced by a
simple list constructor:

>>> [ y for y in itertools.chain.from_iterable(x)]
['A0', 'A1', 'A2', 'B0', 'B1', 'B2', 'C0', 'C1', 'C2']
>>> list(itertools.chain.from_iterable(x))
['A0', 'A1', 'A2', 'B0', 'B1', 'B2', 'C0', 'C1', 'C2']

A bit simpler and achieves the same.

ChrisA

[toc] | [prev] | [next] | [standalone]


#51144

FromTerry Reedy <tjreedy@udel.edu>
Date2013-07-24 11:56 -0400
Message-ID<mailman.5047.1374681415.3114.python-list@python.org>
In reply to#51103
On 7/23/2013 7:02 PM, Terry Reedy wrote:
> On 7/23/2013 5:52 PM, steve@divillo.com wrote:
>> I think that itertools may be able to do what I want but I have not
>> been able to figure out how.

What you want is a flattened product with unchanged components of the 
successive products omitted in the flattening. The omission is the 
difficulty.

> A recursive generator suffices.

But see below for how to use itertools.product.

>> I want to convert an arbitrary number of lists with an arbitrary
>> number of elements in each list into a single list as follows.

While others answered the Python2-oriented question ("How do I produce a 
list from a list of lists"), I answered the Python-3 oriented question 
of how to produce an iterator from an iterable of iterables. This scales 
better to an input with lots of long sequences. There is usually no need 
to manifest the output as a list, as the typical use of the list will be 
to iterate it.

> def crossflat(lofl):
>      if lofl:
>          first = lofl.pop(0)
>          for o in first:
>             yield o
>             yield from crossflat(lofl.copy())
>
> A0, A1, A2 = 100, 101, 102
> B0, B1, B2 = 10, 11, 12
> C0, C1, C2 = 0, 1, 2
> LL = [[A0, A1, A2], [B0, B1, B2], [C0, C1, C2]]
> cfLL = list(crossflat(LL))
> print(cfLL)
> assert cfLL == [
>     A0, B0, C0, C1, C2, B1, C0, C1, C2, B2, C0, C1, C2,
>     A1, B0, C0, C1, C2, B1, C0, C1, C2, B2, C0, C1, C2,
>     A2, B0, C0, C1, C2, B1, C0, C1, C2, B2, C0, C1, C2]
>
> passes

Here is filtered flattened product version. I think it clumsier than 
directly producing the items wanted, but it is good to know of this 
approach as a backup.

from itertools import product

def flatprod(iofi):  # iterable of iterables
     lofi = list(iofi)
     now = [object()] * len(lofi)
     for new in product(*lofi):
         i = 0
         while now[i] == new[i]:
             i += 1
         yield from new[i:]
         now = new

cfLL = list(flatprod(LL))

Same assert as before passes.

-- 
Terry Jan Reedy

[toc] | [prev] | [next] | [standalone]


#51158

Fromsteve@divillo.com
Date2013-07-24 11:11 -0700
Message-ID<2f857fe1-256f-48e7-9ad6-b686c84d32d6@googlegroups.com>
In reply to#51103
Wow, thanks everyone. Very helpful indeed!

On Tuesday, July 23, 2013 2:52:21 PM UTC-7, st...@divillo.com wrote:
> I think that itertools may be able to do what I want but I have not been able to figure out how.
> 
> 
> 
> I want to convert an arbitrary number of lists with an arbitrary number of elements in each list into a single list as follows.
> 
> 
> 
> Say I have three lists:
> 
> 
> 
> [[A0,A1,A2], [B0,B1,B2] [C0,C1,C2]]
> 
> 
> 
> I would like to convert those to a single list that looks like this:
> 
> 
> 
> [A0,B0,C0,C1,C2,B1,C0,C1,C2,B2,C0,C1,C2,A1,B0,C0,C1,C2,B1,C0,C1,C2,B2,C0,C1,C2,A2,B0,C0,C1,C2,B1,C0,C1,C2,B2,C0,C1,C2]
> 
> 
> 
> An easier way to visualize the pattern I want is as a tree.
> 
> 
> 
> A0
> 
> 	B0
> 
> 		C0
> 
> 		C1
> 
> 		C2
> 
> 	B1
> 
> 		C0
> 
> 		C1
> 
> 		C2
> 
> 	B2
> 
> 		C0
> 
> 		C1
> 
> 		C2
> 
> A1
> 
> 	B0
> 
> 		C0
> 
> 		C1
> 
> 		C2
> 
> 	B1
> 
> 		C0
> 
> 		C1
> 
> 		C2
> 
> 	B2
> 
> 		C0
> 
> 		C1
> 
> 		C2
> 
> A2
> 
> 	B0
> 
> 		C0
> 
> 		C1
> 
> 		C2
> 
> 	B1
> 
> 		C0
> 
> 		C1
> 
> 		C2
> 
> 	B2
> 
> 		C0
> 
> 		C1
> 
> 		C2

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web