Thursday, December 26, 2024
Google search engine
HomeLanguagesPython | Reshape a list according to given multi list

Python | Reshape a list according to given multi list

Given two lists, a single dimensional and a multidimensional list, write Python program to reshape the single dimensional list according to the length of multidimensional list. 

Examples:

Input : list1 = [[1], [2, 3], [4, 5, 6]]
        list2 = ['a', 'b', 'c', 'd', 'e', 'f']
Output : [['a'], ['b', 'c'], ['d', 'e', 'f']]

Input : list1 = [[8, 2, 5], [1], [12, 4, 0, 24]]
        list2 = ['m', 'n', 'o', 'p', 'q', 'r', 's', 't']
Output : [['m', 'n', 'o'], ['p'], ['q', 'r', 's', 't']]

  Method #1 : Using extended slices A simple and naive method is to use a for loop and Python extended slices to append each sublist of list2 to a variable ‘res’. 

Python3




# Python3 program to reshape a list
# according to multidimensional list
         
def reshape(lst1, lst2):
    last = 0
    res = []
    for ele in list1:
        res.append(list2[last : last + len(ele)])
        last += len(ele)
         
    return res
 
# Driver code
list1 = [[1], [2, 3], [4, 5, 6]]
list2 = ['a', 'b', 'c', 'd', 'e', 'f']
print(reshape(list1, list2))


Output:

[['a'], ['b', 'c'], ['d', 'e', 'f']]

  Method #2 : islice from itertools module Another method is to use islice function from itertools module. islice selectively prints the values mentioned in its iterable container. Thus, we yield slices of list2 according to list1 and append it to variable ‘res’. 

Python3




# Python3 program to reshape a list
# according to multidimensional list
from itertools import islice
 
def yieldSublist(lst1, lst2):
    iter2 = iter(lst2)
    for sublist1 in lst1:
        sublist2 = list(islice(iter2, len(sublist1)))
        yield sublist2
         
def reshape(lst1, lst2):
    res = list()
    for sub2 in yieldSublist(list1, list2):
        res.append(sub2)
         
    return res
 
# Driver code
list1 = [[1], [2, 3], [4, 5, 6]]
list2 = ['a', 'b', 'c', 'd', 'e', 'f']
print(reshape(list1, list2))


Output:

[['a'], ['b', 'c'], ['d', 'e', 'f']]

  Method #3 : Python iterator with list comprehension The iter() method returns an iterator for list2 and save it in variable ‘iterator’. Now using list comprehension reshape list2 according to list1. 

Python3




# Python3 program to reshape a list
# according to multidimensional list
 
def reshape(lst1, lst2):
    iterator = iter(lst2)
    return [[next(iterator) for _ in sublist]
                         for sublist in lst1]
 
# Driver code
list1 = [[1], [2, 3], [4, 5, 6]]
list2 = ['a', 'b', 'c', 'd', 'e', 'f']
print(reshape(list1, list2))


Output:

[['a'], ['b', 'c'], ['d', 'e', 'f']]

 Method #4 : Using the yield keyword and a for loop:
This approach uses the yield keyword to generate a sequence of sublists, which can then be converted to a list using the list function.

Python3




def reshape(lst1, lst2):
    # Iterate over the elements in lst1
    for sublist in lst1:
        # Yield a sublist containing the first len(sublist) elements of lst2
        yield [lst2.pop(0) for _ in range(len(sublist))]
 
# Test the function
list1 = [[1], [2, 3], [4, 5, 6]]
list2 = ['a', 'b', 'c', 'd', 'e', 'f']
print(list(reshape(list1, list2)))
#This code is contributed by Edula Vinay Kumar Reddy


Output

[['a'], ['b', 'c'], ['d', 'e', 'f']]

# Time complexity: O(n), where n is the total number of elements in lst1 and lst2
# Space complexity: O(n), since the function generates a sequence of sublists that may require up to O(n) space to store

Approach#5: Using Slicing

In this approach, we iterate through the given list list1 and for each sub-list lst in it, we create a new sub-list by taking the first len(lst) elements from list2. We do this using slicing and return the list of all the new sub-lists.

Algorithm

1. Create an empty list result.
2. For each sub-list lst in list1, create a new sub-list by taking the first len(lst) elements from list2 using slicing.
3. Append the new sub-list to result.
4. Return result.

Python3




def reshape_list(list1, list2):
    result = []
    for lst in list1:
        new_lst = list2[:len(lst)]
        list2 = list2[len(lst):]
        result.append(new_lst)
    return result
 
list1 = [[1], [2, 3], [4, 5, 6]]
list2 = ['a', 'b', 'c', 'd', 'e', 'f']
print(reshape_list(list1, list2))


Output

[['a'], ['b', 'c'], ['d', 'e', 'f']]

Time Complexity: O(n^2) where n is the length of the longest sub-list in list1. This is because we are using slicing inside the loop, which has a time complexity of O(n).
Space Complexity: O(n) where n is the length of list2. We are using a new list new_lst for each sub-list in list1.

METHOD 6:using defaultdict: The defaultdict approach creates a dictionary of sublists where each sublist corresponds to a sublist in list1. It then iterates over the sublists and their elements in list1, and appends elements from list2 to the corresponding sublist in the dictionary. Finally, it extracts the sublists from the dictionary in the order of list1 to form the final result. 

  • Initialize an empty dictionary using defaultdict. The keys of the dictionary will correspond to the indices of the sublists in list1.
  • Iterate over the sublists in list1 using a nested loop. For each sublist, iterate over its elements and append the next element from list2 to the corresponding dictionary value.
  • Extract the sublists from the dictionary in the order of list1 to obtain the reshaped list.

Python3




from collections import defaultdict
 
list1 = [[1], [2, 3], [4, 5, 6]]
list2 = ['a', 'b', 'c', 'd', 'e', 'f']
 
# Use defaultdict to create a
# dictionary of sublists
d = defaultdict(list)
 
for i, sublist in enumerate(list1):
    for j, elem in enumerate(sublist):
        d[i].append(list2.pop(0))
 
# Extract the sublists from dictionary
# in the order of list1
result = [d[i] for i in range(len(list1))]
 
print(result)


Output

[['a'], ['b', 'c'], ['d', 'e', 'f']]

Time complexity: O(m * n), where m is the number of sublists in list1 and n is the maximum length of any sublist.

Space complexity: O(m * n), since we need to store the reshaped list in memory.

Using numpy:

Here’s a step-by-step breakdown of the algorithm:

flat_lst1 = np.concatenate(lst1).ravel(): Convert lst1 into a 1D NumPy array (flat_lst1) by concatenating all the sublists in lst1, and flattening the resulting array.

if len(flat_lst1) != len(lst2): raise ValueError(“The total number of elements in lst1 and lst2 do not match.”): Check if the total number of elements in flat_lst1 and lst2 match. If not, raise a ValueError with a message indicating that the total number of elements in lst1 and lst2 do not match.

cum_lengths = np.cumsum([0] + [len(sublst) for sublst in lst1]): Calculate the cumulative lengths of each sublist in lst1. This is done by creating a list of the lengths of each sublist in lst1, and using NumPy’s cumsum() function to calculate the cumulative sums of those lengths. The 0 at the beginning of the list ensures that the cumulative sum starts at 0.

return [lst2[cum_lengths[i]:cum_lengths[i+1]] for i in range(len(lst1))]: Create a list of sublists of lst2, where the i-th sublist contains the elements corresponding to the i-th sublist of lst1. This is done by using a list comprehension to iterate over the indices of lst1 and slicing lst2 using the corresponding start and end indices from cum_lengths.

Python3




import numpy as np
 
def reshape(lst1, lst2):
    flat_lst1 = np.concatenate(lst1).ravel() # convert lst1 into a 1D numpy array
    if len(flat_lst1) != len(lst2):
        raise ValueError("The total number of elements in lst1 and lst2 do not match.")
    cum_lengths = np.cumsum([0] + [len(sublst) for sublst in lst1]) # calculate the cumulative lengths of each sublist in lst1
    return [lst2[cum_lengths[i]:cum_lengths[i+1]] for i in range(len(lst1))] # return a list of sublists of lst2, where the i-th sublist contains the elements corresponding to the i-th sublist of lst1
 
# example usage
list1 = [[1], [2, 3], [4, 5, 6]]
list2 = ['a', 'b', 'c', 'd', 'e', 'f']
print(reshape(list1, list2)) # output: [['a'], ['b', 'c'], ['d', 'e', 'f']]


output: 

[[‘a’], [‘b’, ‘c’], [‘d’, ‘e’, ‘f’]]
 

Time complexity: O(n), where n is the total number of elements in lst1 and lst2.

Auxiliary Space: O(n), since the function generates a new list of sublists that may require up to O(n) space to store.

RELATED ARTICLES

Most Popular

Recent Comments