Subham Saha
Subham Saha

Reputation: 249

Dynamically create loops to iterate over a List of List<String>'s

I have a List of List<String>'s which I get from a external API method call:

List<List<String>> outerList

I have to create unique key combinations by concatenating strings from each list in the same order they are in the outer list.

Example: If outer list has 2 inner lists, say list1: {"A","B"} and list2: {"C","D"}. Then possible unique combinations will be AC, AD, BC and BD.

But the problem is the outerList size is dynamic, it can contain any number of inner lists. If the inner list numbers are fixed then I can write for loops and create combinations.

I am thinking in the direction of using reflections, recursion etc but so far have not been able to solve it.

public static void main(String[] args) {

    List<List<String>> outerList = new ArrayList<List<String>>();
    List<String> list1 = new ArrayList<String>();
    list1.add("A");
    list1.add("B");
    List<String> list2 = new ArrayList<String>();

    list2.add("C");
    list2.add("D");
    outerList.add(list1);

    outerList.add(list2);

    for(String s1: list1) {
        for(String s2: list2) {
            System.out.println(s1+s2);
        }
    }
}

Here outerList has 2 inner lists so I have created 2 for loops explicitly to iterate and concatenate. But in real-time outerList can have any number of inner lists, how to loop dynamically loop through all the inner loops and concatenate?

Upvotes: 2

Views: 4998

Answers (2)

Tobias
Tobias

Reputation: 9380

This code works for me:

public class Test
{  

    public static void generate(LinkedList<LinkedList<String>> outerList, String outPut) {
        LinkedList<String> list = outerList.get(0);

        for(String str : list) {
            LinkedList<LinkedList<String>> newOuter = new LinkedList<LinkedList<String>>(outerList);
            newOuter.remove(list);

            if(outerList.size() > 1) {
                generate(newOuter, outPut+str);
             } else {
               System.out.println(outPut+str);
             }
        }
    }

    public static void main(String[] args) 
    {
        LinkedList<LinkedList<String>> outerList = new LinkedList<LinkedList<String>>();

        LinkedList<String> list1 = new LinkedList<String>();
        LinkedList<String> list2 = new LinkedList<String>();

        list1.add("A");
        list1.add("B");

        list2.add("C");
        list2.add("D");

        outerList.add(list1);
        outerList.add(list2);

        Test.generate(outerList, "");
    }      
}

Output:

AC
AD
BC
BD

Upvotes: 5

Daniel Earwicker
Daniel Earwicker

Reputation: 116714

Sample data with enough variation to demonstrate the problem:

    List<List<String>> outerList = new ArrayList<List<String>>();

    List<String> innerList1 = new ArrayList<String>();
    innerList1.add("A");
    innerList1.add("B");
    outerList.add(innerList1);

    List<String> innerList2 = new ArrayList<String>();
    innerList2.add("X");
    innerList2.add("Y");
    innerList2.add("Z");
    outerList.add(innerList2);

    List<String> innerList3 = new ArrayList<String>();
    innerList3.add("P");
    innerList3.add("Q");
    innerList3.add("R");
    outerList.add(innerList3);

Keep an array of counters:

    int[] positions = new int[outerList.size()];

    boolean another = true;
    while (another) {
        for (int n = 0; n < outerList.size(); n++) {
            System.out.print(outerList.get(n).get(positions[n]));
        }
        System.out.println();

        another = false;
        for (int c = 0; c < outerList.size(); c++) {
            positions[c]++;
            if (positions[c] < outerList.get(c).size()) {
                another = true;
                break;
            }
            positions[c] = 0;
        }
    }

Each time around the main loop, I print one item from each inner list. Then I advance the counters, starting with the first. If that doesn't go off the end of the first inner list, we're ready to print again. But if it does, I set that counter to zero and try advancing the second one, and so on. If they all wrap round to zero, it's time to quit.

It's really just like counting except that the columns each have a different "base" (instead of all being base ten or two or whatever).

Upvotes: 1

Related Questions