L. Amber O'Hearn
L. Amber O'Hearn

Reputation: 308

Python list comprehension to map from flat list to mimic a nested structure

In a recent question, thefourtheye showed a neat list comprehension to map a list to a nested list:

list1 = [1, 2, 3, 4, 5]
list2 = [[1, 2, 3], [5], [1, 6], [1, 0, 9, 10], [1, 5, 2]]
print [(item1, s) for item1, item2 in zip(list1, list2) for s in item2]

Output

[(1, 1), (1, 2), (1, 3), (2, 5), (3, 1), (3, 6), (4, 1), (4, 0), (4, 9), (4, 10), (5, 1), (5, 5), (5, 2)]

My question is related.

Is there a list comprehension to take a flat list of n elements, and map it into the structure of a nested list with n basic elements?:

list1 = [3, 5, 4, 1, 2, 6, 0, 7]
list2 = [ [0,1], [2,3,4], [5], [6,7] ]

output

[ [3,5], [4,1,2], [6], [0,7] ]

I have an ugly loop for it, but can't quite seem to make it come out in a comprehension.

ETA: Hmm. I see some cool answers based on the integer type I used in the example. I should have added that it needs to work on strings.

Let me be more transparent and precise.

I have a sentence that has been broken into space-based tokens and subtokens, and a flat list of replacement tokens.

list2 = [['This'], ['is'], ['a'], ['sentence'], ['I', "'d"], ['like'], ['to'], ['manipulate', '.']]
list1 = ['These', 'were', 'two', 'sentences', 'I', "'d", 'like', 'to', 'read'.]

output = [['These'], ['were'], ['two'], ['sentences'], [['I'], ["'d"]], ['like'], ['to'], ['read', '.']]

Upvotes: 3

Views: 243

Answers (4)

BlackMamba
BlackMamba

Reputation: 10252

Maybe you can try this:

list1 = [3, 5, 4, 1, 2, 6, 0, 7]
list2 = [ [0,1], [2,3,4], [5], [6,7] ]
print([list1[l[0] : l[0] + len(l)] for l in list2])

Upvotes: 0

John La Rooy
John La Rooy

Reputation: 304215

This method relies just on the "shape" of list2, not the contents

>>> list1 = [3, 5, 4, 1, 2, 6, 0, 7]
>>> list2 = [ [0,1], [2,3,4], [5], [6,7] ]
>>> it = iter(list1)
>>> [[next(it) for i in el] for el in list2]
[[3, 5], [4, 1, 2], [6], [0, 7]]

With the string example

>>> list2 = [['This'], ['is'], ['a'], ['sentence'], ['I', "'d"], ['like'], ['to'], ['manipulate', '.']]
>>> list1 = ['These', 'were', 'two', 'sentences', 'I', "'d", 'like', 'to', 'read','.']
>>> it = iter(list1)
>>> [[next(it) for i in el] for el in list2]
[['These'], ['were'], ['two'], ['sentences'], ['I', "'d"], ['like'], ['to'], ['read', '.']]

Upvotes: 6

Jon Clements
Jon Clements

Reputation: 142176

Use a nested list-comp to use the values from the second list to get the first:

list1 = [3, 5, 4, 1, 2, 6, 0, 7]
list2 = [ [0,1], [2,3,4], [5], [6,7] ]    
list3 = [[list1[i] for i in el] for el in list2]
# [[3, 5], [4, 1, 2], [6], [0, 7]]

Upvotes: 1

recursive
recursive

Reputation: 86084

This seems to work.

>>> [[list1[i] for i in s] for s in list2]
[[3, 5], [4, 1, 2], [6], [0, 7]]

Upvotes: 1

Related Questions