Home > Back-end >  Create function which combines 4 lists on top of each other?
Create function which combines 4 lists on top of each other?

Time:03-25

I am trying to make a function which takes in 4 nested lists as input and returns a single conjoined nested list of the 4 input lists combined in a square shape. The first list would be the upper left corner, second list upper right, third bottom left, fourth bottom right. Note, the length of all 4 lists will always be the same. Also, the amount of elements in the inner lists will always equal the amount of inner lists.

For example, if the input is: list1=[[1,2], [3,4]], list2=[[2,1], [4,3]], list3=[[3,4], [1,2]], list4=[[4,3], [2,1]]

the output would be [[1,2,2,1], [3,4,4,3], [3,4,4,3], [1,2,2,1]] because it would be visualized as:

List1 List2
[1,2] [2,1] 
[3,4] [4,3]
List3 List4
[3,4] [4,3]
[1,2] [2,1]

Right now, The pseudocode I have been able to come up with is as follows:

function combine(l1, l2, l3, l4):
    list final = [];
    for (int i = 0; i < (l1.length * 2; i  ):
        list new = [];
        for (int j = 0; j < l1.length; j  ):
            new.append(i'th list[j]);
        final.append(new);
    return final;

I can't seem to figure out how to access the correct elements of the correct array to perform this because this function should perform correctly for any set of 2^n * 2^n arrays.

Any help would be greatly appreciated!

CodePudding user response:

I cannot see that you have specified any language requirement, so even though your list examples suggest that you may not be using C#, I will suggest a C# approach that uses Linq operations Enumerable.Concat() and Enumerable.Zip().

(Hopefully the idea could be helpful, even if you can't use the specific implementation.)

The idea is the following:

  1. Concatenate the elements (element by element) of list1 and list2
  2. Concatenate the elements (element by element) of list3 and list4
  3. Concatenate the result obtained in the first step with the result obtained in the second step

Element-wise concatenation of lists with the same length is straight forward when using the .Zip() operation, as it lets you operate on two sequences element-wise. In this approach, I am using the overload that takes two sequences and defines a result selector. The result selector lets you define what should be done with each element pair of the two sequences.

The "square combination" can be generated as follows:

List<List<int>> squareCombined = list1
    .Zip(list2, ( el1, el2 ) => el1.Concat(el2).ToList())
    .Concat(list3
        .Zip(list4, ( el3, el4 ) => el3.Concat(el4).ToList()))
    .ToList();

In the first .Zip() operation, the sequences are list1 and list2. The result selector is

( el1, el2 ) => el1.Concat(el2).ToList()

, where el1 references an element from list1 and el2 references an element from list2. el1 and el2 will always have the same index in their respective sequence.

In the example you have provided, list1 and list2 look as follows:

{ { 1, 2 }, { 3, 4 } } // list1
{ { 2, 1 }, { 4, 3 } } // list2

For the first element pair in the first .Zip() operation, the result selector therefore produces:

// ( { 1, 2 }, { 2, 1 } ) => { 1, 2 }.Concat({ 2, 1 }).ToList()
{ 1, 2, 2, 1 }

Similarily, for the second element pair in the first .Zip() operation, the result selector produces:

// ( { 3, 4 }, { 4, 3 } ) => { 3, 4 }.Concat({ 4, 3 }).ToList()
{ 3, 4, 4, 3 }

The return value from the first .Zip() operation is an IEnumerable<List<int>> containing those two lists:

{
    { 1, 2, 2, 1 },
    { 3, 4, 4, 3 }
}

By performing an identical .Zip() operation on list3 and list4, and then concatenating the two resulting IEnumerable<List<int>> objects, you obtain a single collection.


This implementation uses the System, System.Collections.Generic and System.Linq namespaces.

Example fiddle here.

  • Related