开发者

Algorithm to map one key values to another key's values in the Map

开发者 https://www.devze.com 2023-03-22 01:26 出处:网络
I have some Maps which I would like to calculate the cartesian product of. Can someone please suggest a good algorithm:

I have some Maps which I would like to calculate the cartesian product of. Can someone please suggest a good algorithm:

Data:

Key1    {100,101,102}

Key2    {200,201}

Key3    {300}

Required Output: (Order does matter)

100,200,300
101,200,300
102,200,300
10开发者_运维知识库0,201,300
101,201,300
102,201,300

Map is dynamic so Key and values can vary in size.

Thanks.


You will want to switch to using a LinkedHashMap so that order is preserved when you're iterating over keys.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class CartesianPrint {

    public static void main(String[] args) {
        Map<Integer,List<Integer>> groupMap = new LinkedHashMap<Integer,List<Integer>>();

        groupMap.put(1,Arrays.asList(new Integer[]{100,101,102}));
        groupMap.put(2,Arrays.asList(new Integer[]{200,201}));
        groupMap.put(3,Arrays.asList(new Integer[]{300}));

        List<List<Integer>> values = new ArrayList<List<Integer>>(groupMap.values());
        int[] printList = new int[values.size()];
        print(values,printList,values.size()-1);        
    }

    static void print(List<List<Integer>> values, int[] printList, int level){
        for (Integer value: values.get(level)) {
            printList[level] = value;
            if(level == 0){
                 System.out.println(Arrays.toString(printList));
            }else{
                 print(values,printList,level-1);
            }
        }       
    }

}


Same as Ondra Žižka, if you don't need a map, take a List it works the same way. Here is a not so optimized way (I should clone instead of recalculating product in recursion. But the idea is still here and its pretty short. I took special care to keep correct order, that's why I run through List backwards.

    public static List<List<Integer>> getCart(List<List<Integer>> a_list) {
        List<List<Integer>> l_result = new ArrayList<List<Integer>>();
        if (a_list == null || a_list.isEmpty()) {
            l_result.add(new ArrayList<Integer>());
            return l_result;
        }
        for (Integer l_value : a_list.get(a_list.size()-1)) {
            List<List<Integer>> l_resultPortion = getCart(a_list.subList(0, a_list.size() - 1));
            for (List<Integer> l_list : l_resultPortion) {
                l_list.add(l_value);
            }
            l_result.addAll(l_resultPortion);
        }
        return l_result;
    }


I suggest to create a store of tuples (triplet in your example).

List<List<Integer>> store = new LinkedList();

Then create a Stack of numbers.

Stack<Integer> stack = new Stack();

Then write a recursive function:

In each recursive function call, push the actually processed value of the array into the stack, and add the current tuple to the store.

private static process( Iterator<String> keys ){
    // Bottom-most key
    if( ! keys.hasNext() ){
        // Construct the tuple from the stack and add it to store.
    }
    else {
       String currentKey = keys.next();
       List<Integer> numbers = map.get( currentKey );
       for( int i : numbers ){
          stack.push( i );
          process ( keys );
          stack.pop();  // Dispose processed number.
       }
    }
}

I hope I figured out the problem right (no guarantee). Sorry for not implementing it whole but that's your homework :)

0

精彩评论

暂无评论...
验证码 换一张
取 消