Converting a list of lists to a single list

S

steve

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
 
R

Rafael Durán Castañeda

El 23/07/13 23:52, (e-mail address removed) 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
 
Z

Zero Piraeus

:

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.
 
M

MRAB

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))
 
T

Terry Reedy

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
 
D

Dennis Lee Bieber

El 23/07/13 23:52, (e-mail address removed) 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']
 
C

Chris Angelico

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
 
T

Terry Reedy

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.

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 == new:
i += 1
yield from new[i:]
now = new

cfLL = list(flatprod(LL))

Same assert as before passes.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top