Pra Do
Pra Do

Reputation: 293

How to count the repetition of duplicate elements that are in arrays?

I was able to count the repetition elements but not in an efficient way. Basically i have an array list that is of type String. Example:

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

if i print s using foreach then output is:

[1,2]
[1,4]
[4]
[3,5]

What is an efficient way to count repetition of numbers when there are multiple arrays? Any kind of help is appreciated.

Final Output: 1 is 2 times repeated. 2 is 1 time repeated. so on

Upvotes: 1

Views: 321

Answers (2)

Donald Raab
Donald Raab

Reputation: 6686

If you are open to using a third party library, you could use GS Collections which has support for primitive bags. Bag is a data structure that keeps track of the occurrences of each unique element. Using an IntBag can reduce the amount of boxing you would otherwise need for your use case.

CharAdapter remove = CharAdapter.adapt("[]");
IntBag counts =
    Lists.mutable.with("[1,2]", "[1,4]", "[4]", "[3,5]")
        .asLazy()
        .collectWith(StringIterate::rejectChar, remove::contains)
        .flatCollect(StringIterate::csvTokensToList)
        .collectInt(Integer::parseInt)
        .toBag();
Assert.assertEquals(2, counts.occurrencesOf(1));
Assert.assertEquals(1, counts.occurrencesOf(2));

If you need the output sorted by value, you can use a SortedBag<Integer> instead. Note however, this will result in boxing the ints to Integers.

CharAdapter remove = CharAdapter.adapt("[]");
SortedBag<Integer> counts =
    Lists.mutable.with("[1,2]", "[1,4]", "[4]", "[3,5]")
        .asLazy()
        .collectWith(StringIterate::rejectChar, remove::contains)
        .flatCollect(StringIterate::csvTokensToList)
        .collect(Integer::parseInt)
        .toSortedBag();
Assert.assertEquals(2, counts.occurrencesOf(1));
Assert.assertEquals(1, counts.occurrencesOf(2));
System.out.println(counts.toStringOfItemToCount());

Outputs:

{1=2, 2=1, 3=1, 4=2, 5=1}

Note: I am a developer on GS Collections

Upvotes: 2

assylias
assylias

Reputation: 328588

You could use a counting collector:

public static void main(String[] args) {
  List<String> s = Arrays.asList("[1,2]", "[1,4]", "[4]", "[3,5]");
  Map<Integer, Long> occurences = s.stream()
                  .flatMap(abc::parseString)
                  .collect(groupingBy(i -> i, counting()));
  System.out.println("occurences = " + occurences);
}

private static Stream<Integer> parseString(String s) {
  String[] numbers = s.substring(1, s.length() - 1).split(",");
  return Arrays.stream(numbers).map(Integer::parseInt);
}

output:

occurences = {1=2, 2=1, 3=1, 4=2, 5=1}

Upvotes: 1

Related Questions