简体   繁体   中英

Java recursively remove elements from Arraylist of Arraylists

I'm writing a software in which I have to deal with ArrayList<ArrayList<Integer>> . What I have to do is to remove duplicates in the sublists, starting from the shortest one and removing those values from the other sublists if they exist, and so on iteratively since there are no more duplicates. For example, my original list of lists is:

[[4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31], 
[26, 27, 28, 29, 30, 31], 
[11, 12, 13, 14], 
[13, 14], [9, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]]

and the final result I want is the following:

[[4, 5, 6, 7, 8, 15, 16, 17, 18, 19, 20], 
[26, 27, 28, 29, 30, 31], 
[11, 12], 
[13, 14], [9, 22, 23, 24, 25]]

From the original list I see that the sub list [13,14] is the shortest and these values are not unique in the main list, then I remove them from all the other sublists:

[[4, 5, 6, 7, 8, 9, 11, 12, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31], 
[26, 27, 28, 29, 30, 31], 
[11, 12], 
[13, 14], [9, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]]

Now the next shortest sublist is [11, 12] and then I remove these two values from all the other lists and so on.

I really have no idea how to write recursive code, any ideas?

EDIT: the number of sublists is not constant.

public class Test6 {

    public static void main(String[] args) throws Exception {

        Integer[] list1 = { 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
        Integer[] list2 = { 26, 27, 28, 29, 30, 31 };
        Integer[] list3 = { 11, 12, 13, 14 };
        Integer[] list4 = { 13, 14 };
        Integer[] list5 = { 9, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };

        ArrayList<ArrayList<Integer>> main = new ArrayList<ArrayList<Integer>>();
        main.add(new ArrayList(Arrays.asList(list1)));
        main.add(new ArrayList(Arrays.asList(list2)));
        main.add(new ArrayList(Arrays.asList(list3)));
        main.add(new ArrayList(Arrays.asList(list4)));
        main.add(new ArrayList(Arrays.asList(list5)));

        for (ArrayList<Integer> list : main) {
            System.out.println(list);
        }

        removeDuplicates(main);

        System.out.println("________________________________________");

        for (ArrayList<Integer> list : main) {
            System.out.println(list);
        }

    }

    private static void removeDuplicates(ArrayList<ArrayList<Integer>> main) {
        // Sort the lists based on their size
        Collections.sort(main, new Comparator<ArrayList<Integer>>() {

            @Override
            public int compare(ArrayList<Integer> o1, ArrayList<Integer> o2) {
                return Integer.valueOf(o2.size()).compareTo(Integer.valueOf(o1.size()));
            }
        });

        for (ArrayList<Integer> list1 : main) {
            for (ArrayList<Integer> list2 : main) {
                if (list2 != list1) {
                    removeDuplicateNumbers(list1, list2);
                }
            }
        }
    }

    private static void removeDuplicateNumbers(ArrayList<Integer> list1, ArrayList<Integer> list2) {
        for (Integer number : list2) {
            list1.remove(number);
        }
    }
}

I wrote this pseudo code in around 30 minutes without the ability to test it so let me know if there are mistakes. You don't really need recursion, but if you are inclined to do recursion you can kinda do it like this (except this isn't the best example of recursion). The idea is to make a copy of the source array. From that copy, find the shortest sub-array and remove all duplicates from the rest of the sub-arrays in the copy. Lastly, place the shortest into the return array, and call the function again, using the modified temp array, and the newly updated return array.

tempArray = actualArray;
returnArray = new Array<Array<int>();
filterList(tempArray, returnArray);

void filterList(<Array<Array<int>> temp, Array<Array<int>> returnArray){
    // If we're done with recursion
    if (temp.isEmpty)
        return;

    // Arbitrarily start with a shortest array. Starting empty would result in staying empty
    Array<int> shortestArray = temp[0];

    // Find our shortest array so we can check list contents.
    for(Array<int> subArray in temp){
        if(subArray.length < shortestArray.length){
            shortestArray = subArray;
        }
    }

    // remove shortest from temp so we can work on the rest of the list.
    temp.remove(shortestArray);

    // Loop through the array and remove all instances of repeated items
    for(i = 0; i < shortestArray.length; i++){
        for(Array<int> subArray in temp){
            if(subArray.contains(shortestArray[i])){
                subArray.remove(shortestArray[i]);
            }
        }
    }

    // Place shortest into return, and then enter recursion.
    returnArray.add(shortestArray);
    filterList(temp, returnArray);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM