Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
78 views
in Technique[技术] by (71.8m points)

java - Find values in ArrayList with specific conditions

I'm trying to create a function that gives a list of arrays and two arrays of integers as input:

public boolean[] checkMatching(ArrayList<String[]> items, Integer[] arr1, Integer[] arr2){...} 

checks if there are at least two items that have the same values for the indices of arr1, but different values for the indices of arr2. For example:

ArrayList<String[]> items = new ArrayList<String[]>();
//All arrays in items have the same number of elements
items.add(new String[]{"B","2","5","6","W"}); //item1
items.add(new String[]{"A","2","5","6","X"}); //item2
items.add(new String[]{"A","2","1","3","Y"}); //item3
items.add(new String[]{"N","F","1","2","W"}); //item4
items.add(new String[]{"A","2","5","6","V"}); //item5

int[] arr1 = new int[] {1,2};
int[] arr2 = new int[] {0,3,4};

boolean[] results = checkMatching(items, arr1, arr2)

In the previous example the function should return:

[-1, 1, -1]

since item1, item2, and item5 share the same values for the indices of arr1, while they have different values for indices 0,4, and equal values for index 3.

Notice that, the method returns 3 integers since in arr2 there are 3 indices. Thus, each boolean refers to an index in arr2.

This could be a solution which exploits functional programming:

public class Temp2 {
    
    public static void main(String[] args) {
        ArrayList<String[]> items = null;

        items = new ArrayList<String[]>();
        items.add(new String[]{"B","2","5","6","W"}); //item1
        items.add(new String[]{"A","2","5","6","X"}); //item2
        items.add(new String[]{"A","2","1","3","Y"}); //item3
        items.add(new String[]{"N","F","1","2","W"}); //item4
        items.add(new String[]{"A","2","5","6","V"}); //item5
        
        int[] arr1 = new int[] {1,2};
        int[] arr2 = new int[] {0,3,4};

        Temp2 tmp = new Temp2();
        int[] results = tmp.checkMatching(items, arr1, arr2);
        
        for(int k = 0; k < 5; k++) {
            System.out.print(results[k]+"|");
        }
        System.out.println();
    }

    public int[] checkMatching(ArrayList<String[]> items, int[] arr, int[] arr2){
        int maxIndex = 4;

        Function<String[], String> compositeKey = el -> getFunctionParametersTest(el, arr);

        Optional<int[]> map = items.stream()
                .collect(Collectors.groupingBy(compositeKey, Collectors.toList())).entrySet().stream()
                .filter(entry -> entry.getValue().size() > 1)
                .map(entry -> {
                    List<String[]> values = entry.getValue();
                    int[] generalResponse = new int[maxIndex+1];

                    if (values.size() > 1) {
                        for (int i = 0; i < arr2.length; i++) {
                            String tmp = "";
                            int risposta = -2;
                            for (String[] e : values) {
                                if(tmp.length() > 0) {
                                    if (tmp.compareTo(e[arr2[i]]) != 0) {
                                        risposta = -1;
                                        break;
                                    } else {
                                        risposta = 1;
                                    }
                                }
                                else {
                                    tmp = e[arr2[i]];
                                }
                            }
                            generalResponse[i] = risposta;
                        }
                    }
                    return generalResponse;
                }).reduce((a, b) -> {
                    int[] arrLocal = a;
                    int[] arrarrLocal2 = b;
                    int[] sum = new int[a.length];
                    for (int k = 0; k < arrLocal.length; k++) {
                        if (arrLocal[k] == -1 || arrarrLocal2[k] == -1) {
                            sum[k] = -1;
                        } else if (arrLocal[k] >= arrarrLocal2[k]) {
                            sum[k] = arrLocal[k];
                        } else if (arrLocal[k] < arrarrLocal2[k]) {
                            sum[k] = arrarrLocal2[k];
                        }
                    }
                    return sum;
                });

        int[] finalresults = null;
        if (map.isEmpty() == false) {
            finalresults = map.get();
        } else {
            finalresults = new int[maxIndex+1];
            for (int k = 0; k < maxIndex; k++) {
                finalresults[k] = 1;
            }
        }

        return finalresults;
    }
    
    public String getFunctionParametersTest(String[] item, int[] arr) {
        String values = "";
        for (Integer i : arr) {
            values += item[i] + "-";
        }
        return values;
    }

}

But it is not very efficient, especially when there is a large amount of items. Is there anyone who can help me? I am trying to develop a very performing solution and I don't know if there are faster solutions than functional programming.

question from:https://stackoverflow.com/questions/65881032/find-values-in-arraylist-with-specific-conditions

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Based on what I understand I came out with the following solution. However, I am not sure if any list that matches arr1 is what you would want to compare arr2 with. You might need to change the findAny() section in case it is different.

public static Boolean[] checkMatching(ArrayList<String[]> items, final int[] arr1, final int[] arr2) {
    // Gets a list containing items that match arr1.
    List<String[]> list = items.stream().collect(Collectors.groupingBy(item ->
            // Groups items together which match in arr1 indexes.
            // Get a stream of indexes contained in arr1.
            Arrays.stream(arr1)
                    // Get a stream of Strings in those indexes.
                    .mapToObj(i -> Arrays.stream(item).collect(Collectors.toList()).get(i))
                    // A list of these Strings is the groupingBy classifier.
                    .collect(Collectors.toList()) 
        )).values().stream().filter(l -> l.size() > 1) // Just get those groups that have more than 1 element.
        .findAny() // Would you want any list that matches arr1?
        .get();

    // Converts arr2 to a Boolean array which says if each index matches all the items in "list".
    Boolean[] matching = Arrays.stream(arr2).mapToObj(i -> list.stream().map(item -> item[i]).distinct().limit(2).count() < 2).toArray(Boolean[]::new);
    return matching;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...