Home > Blockchain >  How to count duplicates and change List values in ONE for-loop?
How to count duplicates and change List values in ONE for-loop?

Time:11-28

I'm trying to count all the duplicate numbers in the list in my code. In addition, the list should be compared with a set; if there is a match, the respective value should be replaced by another.

I managed to program correctly, but can you get it into a single for loop? If I get it in the same loop, the map always gets the wrong value because the values ​​are always overwritten.

Here is my code:

 public static Map<Integer, Integer> replace(List<Integer> inputList, Set<Integer> numberSet, Integer newNumber) {
        Map<Integer, Integer> map = new HashMap<>();

        for (int i =0; i < inputList.size(); i  ){
            if(numberSet.contains(inputList.get(i))){
                map.put(inputList.get(i), Collections.frequency(inputList, inputList.get(i)));
            }
        }

        for (int i =0; i < inputList.size(); i  ){
            if(numberSet.contains(inputList.get(i))){
                inputList.set(i, newNumber);
            }
        }
        return map;
    }

CodePudding user response:

Using Collections.frequency while altering the list in the same loop is throwing off your numbers. Here is an approach that handles counting frequency with each iteration while at the same time updating the list values equal to newNumber.

If the code you displayed is giving you the output you desire, then here I have written the following single loop solution that does the same.

public static Map<Integer, Integer> replace(List<Integer> inputList, Set<Integer> numberSet, Integer newNumber) {
    Map<Integer, Integer> map = new HashMap<>();

    for (int i = 0; i < inputList.size(); i  ){
        Integer value = inputList.get(i);

        // value already in map, count 1 more
        if(numberSet.contains(value) && map.containsKey(value)) {
            map.put(value, map.get(value)   1);
        
        // value not in map yet, count 1
        } else {
            map.put(value, 1);
        }

        // always set all list items to newNumber
        inputList.set(i, newNumber);
    }
    return map;
}

CodePudding user response:

Actually, Collections.frequency is not needed here at all because it will recalculate the frequency for each element of inputList from the start.

The frequency of elements is conveniently calculated using Map::merge method, so that each matching value is counted and replaced at the same iteration:

public static Map<Integer, Integer> replace(List<Integer> inputList, Set<Integer> numberSet, Integer newNumber) {
    Map<Integer, Integer> map = new HashMap<>();

    for (int i =0; i < inputList.size(); i  ) {
        Integer v = inputList.get(i);
        if(numberSet.contains(v)) {
            map.merge(v, 1, Integer::sum);
            inputList.set(i, newNumber);
        }
    }
    return map;
}

Test:

List<Integer> ints = Arrays.asList(1, 2, 3, 2, 3, 5, 3, 1, 4, 2);
System.out.println(ints);
System.out.println(replace(ints, Set.of(3, 4, 5), 9));
System.out.println(ints);

Output:

  • frequencies of 3, 4, 5 are calculated correctly
  • all occurrences of 3, 4, 5 set to 9
[1, 2, 3, 2, 3, 5, 3, 1, 4, 2]
{3=3, 4=1, 5=1}
[1, 2, 9, 2, 9, 9, 9, 1, 9, 2]
  • Related