Split a list based on another list, but keep the structure the same by repeating the last elements in Python

82 views Asked by At

I have two types of lists. One is always smaller than the other.

I want to split the longer list in sublists based on the length of the smaller list. E.g.,

a = [1,2,3,4]
b = [1,2,3,4,5,6,7,8,9,10]

desired output =

sub_list 1 = [1,2,3,4] , sub_list 2 = [5,6,7,8], sub_list 3 = [7,8,9,10]

Since only two unique items are left in the last list and to preserve the structure of the last sub_list, repeat the elements just before the last unique elements till it gets to the same length as that of the smaller list.

I tried doing this:

def create_sublists(a, b):
    smaller_list_length = len(a)
    num_sublists = len(b) // smaller_list_length

    b_sublists = []
    for i in range(num_sublists):
        start_index = i * smaller_list_length
        end_index = start_index + smaller_list_length
        b_sublist = b[start_index:end_index]

        if len(b_sublist) < smaller_list_length:
            preceding_numbers = b[start_index - smaller_list_length:start_index]
            num_missing = smaller_list_length - len(b_sublist)
            b_sublist = preceding_numbers[-num_missing:] + b_sublist

        b_sublists.append(b_sublist)

    return b_sublists

But this is not always giving the desired result, and it also doesn’t check for which list is smaller automatically.

How can I do it?

6

There are 6 answers

0
theptrk On

Just check the list lengths beforehand. Something like this.

def split_list(a, b):
    smaller_list = a if len(a) < len(b) else b
    larger_list = b if len(a) < len(b) else a

    sub_lists = []
    smaller_list_length = len(smaller_list)
    start_index = 0

    while start_index < len(larger_list):
        end_index = start_index + smaller_list_length
        sub_list = larger_list[start_index:end_index]
        sub_lists.append(sub_list)
        start_index = end_index

    return sub_lists

a = [1, 2, 3, 4]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

result = split_list(a, b)

# Printing the sublists
for i, sublist in enumerate(result, 1):
    print(f"sub_list {i} =", sublist)

-chatgpt

2
Rusty cole On

To split the longer list into sub lists based on the length of the smaller list, you can modify your code to handle cases where the lengths of the lists are not evenly divisible. Here's an updated version of the code that automatically determines the smaller list and produces the desired output:

def create_sublists(a, b):
smaller_list = a if len(a) <= len(b) else b
larger_list = a if len(a) > len(b) else b
smaller_list_length = len(smaller_list)

num_sublists = len(larger_list) // smaller_list_length
remaining_elements = len(larger_list) % smaller_list_length

b_sublists = []
for i in range(num_sublists):
    start_index = i * smaller_list_length
    end_index = start_index + smaller_list_length
    b_sublist = larger_list[start_index:end_index]
    b_sublists.append(b_sublist)

if remaining_elements > 0:
    preceding_numbers = larger_list[-smaller_list_length:]
    last_sublist = preceding_numbers[-remaining_elements:] + smaller_list[:remaining_elements]
    b_sublists.append(last_sublist)

return b_sublists

Now, you can call the create_sublists function with your example lists:

a = [1, 2, 3, 4]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

sublists = create_sublists(a, b)
for i, sublist in enumerate(sublists, 1):
print(f"sub_list {i} = {sublist}")

Output:

sub_list 1 = [1, 2, 3, 4]
sub_list 2 = [5, 6, 7, 8]
sub_list 3 = [7, 8, 9, 10]
4
Guy On

Another way is to create the sublists with a simple loop and edit the last one with a slice in the correct size. If you aren't sure with one the longest you can check the sizes and swap the lists if needed

a = [1, 2, 3, 4]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

if len(a) > len(b):
    a, b = b, a

size = len(a)
lists = [b[i:i+size] for i in range(0, len(b), size)]
lists[-1] = b[-size:]
print(lists) # [[1, 2, 3, 4], [5, 6, 7, 8], [7, 8, 9, 10]]
0
SIGHUP On

You should allow for the lists to be passed to your "splitter" function in any order (smaller/larger or larger/smaller). Then:

def split(a, b):
    _a, _b = (a, b) if len(a) <= len(b) else (b, a)
    m = len(_a)
    result = [_b[offset:offset+m] for offset in range(0, len(_b)-m, m)]
    result.append(_b[-m:])
    return result

a = [1,2,3,4]
b = [1,2,3,4,5,6,7,8,9,10,11]

for n, e in enumerate(split(a, b), 1):
    print(f'sub_list {n} = {e}')

Output:

sub_list 1 = [1, 2, 3, 4]
sub_list 2 = [5, 6, 7, 8]
sub_list 3 = [8, 9, 10, 11]
1
JayK On

This is the answer to your question.


a = [1, 2, 3, 4]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


def createSubLists(a, b):
    # check which list is smaller
    smaller_list = a if len(a) < len(b) else b
    larger_list = b if len(a) < len(b) else a

    # get the number of the subLists that have to be created 
    if len(larger_list) % len(smaller_list) != 0:
        num_of_sub_lists = len(larger_list)//len(smaller_list) + 1
    else:
        num_of_sub_lists = len(larger_list)//len(smaller_list)
        
    # create a list to put subLists into it and the len of every single sublist
    subListLen = len(smaller_list)
    splitted_list = []

    # create first batch of subLists, i.e. for a and b create
    # splitted_list = [[1, 2, 3, 4], [5, 6, 7, 8]]
    for i in range(len(larger_list)):
        if (i+1) % subListLen == 0:
            splitted_list.append(larger_list[i-3:i+1])

    # create the last odd sublist
    if len(splitted_list) != num_of_sub_lists:
        splitted_list.append([])
        for i in range(subListLen, 0, -1):
            splitted_list[-1].append(larger_list[-i])

    # return list containing sub_lists
    return splitted_list

# print subLists in a given format
for i, subList in enumerate(createSubLists(a, b), 1):
    print(f"sub_list {i} = {subList}")

Output:

sub_list 1 = [1, 2, 3, 4]
sub_list 2 = [5, 6, 7, 8]
sub_list 3 = [7, 8, 9, 10]
0
Alain T. On

you can use a list comprehension with subscripts that work backward from the last existing position in each subranges:

c = [b[:i+len(a)][-len(a):] for i in range(0,len(b),len(a))]

print(c)
[[1, 2, 3, 4], [5, 6, 7, 8], [7, 8, 9, 10]]