2

Let's assume the items array consists of the following items {3.1, 3.1, 3.1, 3.2, 3.2, 3.3, 3.4, 3.4, 3.4, 3.4, 3.1, 3.1}

What I want is to count the occurrence of each item in the successive items such that:

3.1 = 3 
3.2 = 2
3.3 = 1
3.4 = 4
3.1 = 2

I wrote the following function:

private void displayItems(List<Double> items) {
        double current_item=0;
        for(int i=0; i<items.size(); i++) {
            int count=1;
            current_item = items.get(i);
            if(i != items.size()) {
                for(int j=i+1; j<items.size(); j++) {
                    double next_item = items.get(j);
                    if(current_item == next_item) {
                        count++;
                    }else {
                        break;
                    }
                }
                System.out.println("item value is " + current_item + " and count is " + count);
            }
        }
    }

I got the following result:

item value is 3.1 and count is 3
item value is 3.1 and count is 2
item value is 3.1 and count is 1
item value is 3.2 and count is 2
item value is 3.2 and count is 1
item value is 3.3 and count is 1
item value is 3.4 and count is 4
item value is 3.4 and count is 3
item value is 3.4 and count is 2
item value is 3.4 and count is 1
item value is 3.1 and count is 2
item value is 3.1 and count is 1

What can I do to show the results like the following:

item value is 3.1 and count is 3
item value is 3.2 and count is 2
item value is 3.3 and count is 1
item value is 3.4 and count is 4
item value is 3.1 and count is 2

Please not that I don't want to count the occurrence of each item in the entire array, I just want to count its occurrence in the successive items only.

user2864740
  • 60,010
  • 15
  • 145
  • 220
Adam Amin
  • 1,406
  • 2
  • 11
  • 23
  • 1
    To count successive items there should 'probably' only be a single loop. – user2864740 Apr 03 '18 at 16:36
  • I think you should loop through the array once, and store the items in a float indexed map, then the value would just be the count. – Fallenreaper Apr 03 '18 at 16:37
  • @Fallenreaper OP wants to count runs, not totals. (See last line of expected result.) – user2864740 Apr 03 '18 at 16:37
  • @user2864740 I couldn't do it with a single loop – Adam Amin Apr 03 '18 at 16:37
  • @AdamAmin I'm saying: it's possible, and will likely lead to the desired result :) Imagine if this setup was given (assuming that `items.size() > 0`): `current_item = items.get(0); for (int i = 1; i < items.size(); i++) { .. }`. There are too many items in the current output because the outer loop is effectively solving the problem 'for every different starting position'. – user2864740 Apr 03 '18 at 16:37
  • Possible duplicate of [Java count occurrence of each item in an array](https://stackoverflow.com/questions/8098601/java-count-occurrence-of-each-item-in-an-array) – Roddy of the Frozen Peas Apr 03 '18 at 16:38
  • 2
    This is **not** a duplicate of *that* question ("Java count occurrence of each item in an array"). See the expected output. – user2864740 Apr 03 '18 at 16:38
  • Same concept with sub-lists. – Roddy of the Frozen Peas Apr 03 '18 at 16:43
  • @RoddyoftheFrozenPeas The OP is asking for how to "count the size of runs (of the same value)". This is not solvable with (trivial) use of Sets or Maps, because Sets and Maps cannot contain duplicates. The other question is about counting total counts. – user2864740 Apr 03 '18 at 16:44
  • Are you trying to count the occurrences of each object by identity or by value? By this, I mean `new Double(3.14) != new Double(3.14)`. If you are checking values, rather than identities, then you should use `equals` instead of `==`. – DodgyCodeException Apr 03 '18 at 16:53

7 Answers7

2

Your code is iterating over the values which were already counted in the previous iterations. A small tweak in the logic works as expected.

private void displayItems(List<Double> items) {
        double current_item=0;
        for(int i=0; i<items.size(); i++) {
            int count=1;
            current_item = items.get(i);
            if(i != items.size()) {
                int j=i+1;
                for(; j<items.size(); j++) {
                    double next_item = items.get(j);
                    if(current_item == next_item) {
                        count++;
                    }else {
                        break;
                    }
                }
                System.out.println("item value is " + current_item + " and count is " + count);
                i = j-1;
            }
        }
    }
Durga Reddy
  • 101
  • 3
2
x[n-1]-x[n]==0 

should be the formula.

public class SuccessiveCounter {
    public static void main(String[] args) throws Exception {
        double[] x = {3.1,3.1,3.1,3.2,3.2,3.1,3.1,3.4,3.4,3.1,3.1};

        for(int n=1,count = 1;n<x.length;n++){
            if(x[n-1]-x[n]==0){
                count++;
            }else{
                System.out.println(x[n]+" "+count);
                count = 1;
            }
        }
    }
}
zawhtut
  • 8,335
  • 5
  • 52
  • 76
1

You can use a map to map the double to how many times it occurs. Then simply loop over the map to print the values.

private static void count(List<Double> numbers)
{
    final Map<Double, Integer> numberToOccurrences = new HashMap<>();
    for(Double num : numbers)
    {
        numberToOccurrences.putIfAbsent(num, 0);
        numberToOccurrences.compute(num, (k, occurrences) -> ++occurrences);
    }
    numberToOccurrences.forEach((num, occurrences) -> 
        System.out.println("Number " + num + " occurs " + occurrences + " times")
    );
}

A few uses of lambdas here which may be considered more advanced, but they often result in the the most concise solution.

Michael
  • 41,989
  • 11
  • 82
  • 128
  • 1
    This will count the total number of items in the list `Number 3.1 occurs 5 times` however the desired output is `3.1 = 3 3.2 = 2 3.3 = 1 3.4 = 4 3.1 = 2` – Anton Balaniuc Apr 03 '18 at 17:04
1

I guess all the above answers are correct but I also wanted to try this with single loop so here it is with single loop:

import java.util.Arrays;
import java.util.List;

public class SuccessiveCount {

    public static void main(String[] args) {
        List<Double> list = Arrays.asList(3.1, 3.1, 3.1, 3.2, 3.2, 3.3, 3.4, 3.4, 3.4, 3.4, 3.1, 3.1);
        double prevValue = list.get(0);
        int count = 0;
        for(int i=0; i < list.size(); i++) {
            if(prevValue == list.get(i)) {
                count++;
            }else {
                System.out.println("item value is "+list.get(i-1)+ " and count is "+ count);
                prevValue = list.get(i);
                count = 1;
            }
            if(list.size() == (i+1)) {
                System.out.println("item value is "+list.get(i-1)+ " and count is "+ count);
            }
        }

    }

}

PS : If anyone wants to make it look more cleaner I am up for suggestions.

Eshu
  • 499
  • 4
  • 15
0

What about making an ArrayList<String>?

ArrayList<String> runs = new ArrayList<String>();

Then storing something like

runs.add(current_item + "," + count);

instead of your print line, Then going through the array list and split each string by the comma to get desired output.

While it may work it is probably not ideal, but still a possible solution.

EDIT: You would go through runs after the nested loop

Makoto
  • 104,088
  • 27
  • 192
  • 230
0

Here are the changes,

int dec = 0;
int inc = 0;
if(current_item == next_item) {
     count++;
     dec = count; //new line
}
else {
     break;
}
}
//new stuff from here, printing "inc" instead of "count" in print statement.
dec--;
inc++;
if(dec==0){
    System.out.println("item value is " + current_item + " and count is " + inc);
}
heethjain21
  • 130
  • 1
  • 9
0

I think this will give the expected result

int count = 1;
        for (int i = 0; i < arr.size(); i++) {
            if (i != 0) {
                if (arr.get(i) - arr.get(i - 1) == 0) {
                    count++;
                } else if (arr.get(i) - arr.get(i - 1) != 0) {
                    System.out.println("Item value is " + arr.get(i - 1) + " and count is " + count);
                    count = 1;
                }
            }
            if (arr.size() == i + 1) {
                System.out.println("Item value is " + arr.get(i) + " and count is " + count);
            }
        }
Mohammad
  • 739
  • 7
  • 22