Nested list of tuples and list of scores

Viewed 133

I have a problem, I will try to explain as best as I can. I have two lists with 3 items each. Each item in list1 has a score in list2.

List1= [[(3,4,5)], [(23,44), (23,5,3), (1,2)], [(23,5), (1,6)]]
List2= [2,4,1]

As you can see in list1, items 2 and 3 have multiple tuples that correspond to their score, I would like to separate them into their scores:

what I want:
List1= [(3,4,5), (23,44), (23,5,3), (1,2), (23,5), (1,6)]
List2= [2,4,4,4,1,1]

or 

List1= [[(3,4,5)], [(23,44)], [(23,5,3)], [(1,2)], [(23,5)], [(1,6)]]
List2= [2,4,4,4,1,1]

so far, I have identified the items that needs changing.

double = [x for x in List1 if len(x)>1]
print(double)

[[(23, 44), (23, 5, 3), (1, 2)], [(23, 5), (1, 6)]]

I have found the index of these items:

indx = [i for y in double for i, x in enumerate(List1) if x== y ]
print(indx)

[1, 2]

I have flattened the nested list to get what I want in list1:

flat_list = [item for sublist in List1 for item in sublist]

[(3, 4, 5), (23, 44), (23, 5, 3), (1, 2), (23, 5), (1, 6)]

However I am not sure how I can change list2.

any help will be appreciated.

Thank you.

7 Answers

One approach (the cryptic one-liner these questions tend to elicit):

l1, l2 = zip(*((tpl, scr) for tpls, scr in zip(List1, List2) for tpl in tpls))
l1
# ((3, 4, 5), (23, 44), (23, 5, 3), (1, 2), (23, 5), (1, 6))
l2
# (2, 4, 4, 4, 1, 1)

The nested generator expression produces the tuple-score pairs, and the zip(*...) pattern transposes those into two separate tuples that we capture via multi assignment. You can easily convert those to lists if you need to.

A more readable and beginner-friendly way:

tuples, scores = [], []
for tpls, scr in zip(List1, List2):
    for tpl in tpls:
        tuples.append(tpl)
        scores.append(scr)

tuples
# [(3, 4, 5), (23, 44), (23, 5, 3), (1, 2), (23, 5), (1, 6)]
scores
# [2, 4, 4, 4, 1, 1]

I would use zip to iterate over the items and scores in tandem.

List1= [[(3,4,5)], [(23,44), (23,5,3), (1,2)], [(23,5), (1,6)]]
List2= [2,4,1]
new1 = []
new2 = []

# iterate over the list of list of tuples and scores in parallel
for item, score in zip(List1, List2):
    # iterate over the tuples in the list of tuples
    for subitem in item:
        new1.append(subitem)
        new2.append(score)

This could be written more succintly as in some of the examples below but for a beginner this is more easily understood.

This should work:

>>> List1= [[(3,4,5)], [(23,44), (23,5,3), (1,2)], [(23,5), (1,6)]]
>>> List2= [2,4,1]
>>> 
>>> new1 = [w for v in List1 for w in v]
>>> new1
[(3, 4, 5), (23, 44), (23, 5, 3), (1, 2), (23, 5), (1, 6)]
>>> 
>>> new2 = [n for s, n in zip(List1, List2) for i in s]
>>> new2
[2, 4, 4, 4, 1, 1]
>>> 

With list comprehension:

List1Modified = [subset for lists in List1 for subset in lists]
List2Modified = [List2[idx] for idx, lists in enumerate(List1) for _ in lists]

print(List1Modified)
print(List2Modified)

>> [(3, 4, 5), (23, 44), (23, 5, 3), (1, 2), (23, 5), (1, 6)]
>> [2, 4, 4, 4, 1, 1]
List1_new=[]
List2_new=[]
for i in range(len(List1)):
    List1_new+=List1[i]
    List2_new+=[List2[i]]*len(List1[i])

Try this:

List2 =[List2[j] for j, i in enumerate(List1) for k in range(len(i))]

List1 = [j for i in List1 for j in i]

Just a hack, building one with list comp and the other as a side effect.

l2 = []
l1 = [l2.append(scr) or tpl for tpls, scr in zip(List1, List2) for tpl in tpls]
Related