TransWikia.com

How can I regroup 'sublists' in a list with Python?

Stack Overflow Asked by Zhengrong on January 9, 2021

How can I regroup ‘sublists’ in a list with Python? For example, I want to regroup the following list:

[[0, 3], [1, 3], [1, 2], [1, 2], [0, 1], [0, 3]].

I want [0, 1] to be grouped with [2, 3]; [0, 2] with [1, 3]; [0, 3] with [1, 2], and left all the rest "coordinates" as single tuple. For example, in this case, I want

the output be:

[[[0, 3], [1, 2]], [[0, 3], [1, 2]], [0, 1], [1, 3]].

(The last two tuples here are "rest")
Is there a way I can achieve this goal? Thanks!!

2 Answers

Since the entries are only 0, 1, 2, 3 and the values are unique in every tuple, it means that the sum of the tuple can be generated by only one pair, except for 3, I mean: [0, 1] is the only tuple wich the sum of values return 1, by the same way [0, 2] is the only one to return 2, but [0,3] and [1,2] return 3, so them require to check if it is a tuple containing one specific value, such as 3

a = [[0, 3], [1, 3], [1, 2], [1, 2], [0, 1], [0, 3]]
b = []
c = []
d_03 = []
d_12 = []
e = []
f = []

list_of_pairs = []
for tuples in a:
    if sum(tuples) == 1:
        b.append(tuples)
        
    elif sum(tuples) == 2:
        c.append(tuples)
        
    elif sum(tuples) == 4:
        e.append(tuples)
        
    elif sum(tuples) == 5:
        f.append(tuples)
    
    #testing if there is a 3 in that tuple as suggested above
    elif sum(tuples) == 3 and 3 in tuples:
        d_03.append(tuples)

    else:
        d_12.append(tuples)
#one way to figure out the perfect range would be compare the len of the lists that match and use the smaller one, so you don not need the else statement      
for i in range(5):
    #compare len with i+1 because python starts counting from 0
    #if there is any element in those lists, their len will be bigger than 0
    if len(b) >= i+1 and len(f) >= i+1:
        #b have [0, 1] only as tuples
        #f have [2, 3] only as tuples
        #so when you append one after the other, they will always match
        list_of_pairs.append(b[i])
        list_of_pairs.append(f[i])
        #pop it so at the end will only be in those lists the ones wich don't have their pair
        b.pop(i)
        f.pop(i)
        #insert blank spaces just so you do not modify the indexes of any elements in the list
        b.insert(i-1, '')
        f.insert(i-1, '')
    else:
        #break it because if you run the conditional above it will return IndexError
        #the following i values would also return this error
        break
    
for i in range(5):
    #same principle for c and e
    #and after for d
    if len(c) >= i+1 and len(e) >= i+1:
        list_of_pairs.append(c[i])
        list_of_pairs.append(e[i])
        c.pop(i)
        e.pop(i)
        c.insert(i-1, '')
        e.insert(i-1, '')
    else:
        break
    
for i in range(5):
    if len(d_12) >= i+1 and len(d_03) >= i+1:
        list_of_pairs.append(d_03[i])
        list_of_pairs.append(d_12[i])
        d_12.pop(i)
        d_03.pop(i)
        d_12.insert(i-1, '')
        d_03.insert(i-1, '')
    else:
        break
    
        
#this final list must have the pairs and also the rest
final_list = []
#append the pairs so it will be presented first and as a list inside the final list
final_list.append(list_of_pairs)
#extend by all the previous lists except for list of pairs and a
#this will put any rest in the final list as separate therms from the pairs
final_list.extend(b)
final_list.extend(c)
final_list.extend(d_03)
final_list.extend(d_12)
final_list.extend(e)
final_list.extend(f)
#now the final list might have some '' as rest
#so you can loop through it removing them
while '' in final_list:
    final_list.remove('')
print(final_list)

This is the output:

[[[0, 3], [1, 2], [0, 3], [1, 2]], [0, 1], [1, 3]]

Correct answer by Voz bonita on January 9, 2021

Assuming you have a list of lists (like in the example, and not actual tuples):

problem = [[0, 3], [1, 3], [1, 2], [1, 2], [0, 1], [0, 3]]

You want to pair these pairs so that each pair contains each of the values in (0, 1, 2, 3) exactly once?

target = [0, 1, 2, 3]

And all the pairs that cannot be matched remain by themselves? This is one way of doing it:

answer = []
while problem:
    # take the first element from problem
    x1 = problem.pop()
    # construct what the paired element should look like
    x2 = [x for x in target if x not in x1]
    try:
        # attempt to remove it from problem
        problem.remove(x2)
        # if the remove succeeds, both x1 and x2 have now been removed, add the pair
        answer.append([x1, x2])
    except ValueError:
        # when trying to remove a non-existent value, a ValueError is raised
        # in that case, there is no matching pair, just add a single
        answer.append(x1)

That's assuming:

  • you never have values in the pairs that don't appear in the target
  • the values in the pairs are always ordered like they are in the target
  • you don't mind that the singles are mixed with the combinations
  • you don't mind that the original problem is modified during the process

Put together:

problem = [[0, 3], [1, 3], [1, 2], [1, 2], [0, 1], [0, 3]]
target = [0, 1, 2, 3]

answer = []
while problem:
    x1 = problem.pop()
    x2 = [x for x in target if x not in x1]
    try:
        problem.remove(x2)
        answer.append([x1, x2])
    except ValueError:
        answer.append(x1)

print(answer)

Result:

[[[0, 3], [1, 2]], [0, 1], [[1, 2], [0, 3]], [1, 3]]

Answered by Grismar on January 9, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP