1

I have a list of lists of lists with strings, something like this (representing chapters, paragraphs and sentences of a text)):

[ [[ ['chp1p1s1'], ['chp1p1s2'], ['chp1p1s3'] ],
   [ ['chp1p2s1'], ['chp1p2s2'], ['chp1p2s3'] ]],
  [[ ['chp2p1s1'], ['chp2p1s2'], ['chp2p1s3'] ],
   [ ['chp2p2s1'], ['chp2p2s2'], ['chp2p2s3'] ]] ]

I know how to flatten this list completly (for example by [x for y in z for x in y]), but what I would like to do is to flatten it partially, to finally look like this:

[ [ ['chp1p1s1'], ['chp1p1s2'], ['chp1p1s3'],
    ['chp1p2s1'], ['chp1p2s2'], ['chp1p2s3'] ],
  [ ['chp2p1s1'], ['chp2p1s2'], ['chp2p1s3'],
    ['chp2p2s1'], ['chp2p2s2'], ['chp2p2s3'] ] ]

I managed to solve this by some for loops:

semiflattend_list=list()
for chapter in chapters:
    senlist=list()
    for paragraph in chapter:
        for sentences in paragraph:
            senlist.append(sentences)
    semiflattend_list.append(senlist)

But I wonder if there is a better, shorter solution? (I don't think, zip is a way to go, because my lists are different in size.)

1
  • 1
    The examples you gave is actually a tuple of two different lists, which I don't think is what you meant. You are messing up the parentheses or a comma, maybe, but we need a reporducible example Commented Apr 11, 2017 at 19:43

1 Answer 1

1

The easiest change I can see is using the itertools.chain method:

q = [
     [[ ['chp1p1s1'], ['chp1p1s2'], ['chp1p1s3'] ],
       [ ['chp1p2s1'], ['chp1p2s2'], ['chp1p2s3'] ]],
     [[ ['chp2p1s1'], ['chp2p1s2'], ['chp2p1s3'] ],
       [ ['chp2p2s1'], ['chp2p2s2'], ['chp2p2s3'] ]]
    ]

r = [list(itertools.chain(*g)) for g in q]
print(r)

[[['chp1p1s1'], ['chp1p1s2'], ['chp1p1s3'], ['chp1p2s1'], ['chp1p2s2'], ['chp1p2s3']],
 [['chp2p1s1'], ['chp2p1s2'], ['chp2p1s3'], ['chp2p2s1'], ['chp2p2s2'], ['chp2p2s3']]]

So, what does [list(itertools.chain(*g)) for g in q] mean:

# If I only had this
[g for g in q]
# I would get the same I started with.
# What I really want is to expand the nested lists

# * before an iterable (basically) converts the iterable into its parts.
func foo(bar, baz):
   print( bar + " " + baz )

lst = ["cat", "dog"]
foo(*lst) # prints "cat dog"

# itertools.chain accepts an arbitrary number of lists, and then outputs 
# a generator of the results:
c = itertools.chain([1],[2])
# c is now <itertools.chain object at 0x10e1fce10>
# You don't want an generator though, you want a list. Calling `list` converts that:
o = list( c )
# o is now [1,2]
# Now, together:
myList = [[2],[3]]
flattened = list(itertools.chain(*myList))
# flattened is now [2,3]
Sign up to request clarification or add additional context in comments.

1 Comment

This actually solved it! Could you maybe please explain this asterisk/splat operator? In the doc it doesn't explain to me how this could help here.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.