Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The sum of the elements of an array [closed]

I have a question for the following scenario;

I have n-number arrays in an ArrayList. The number of arrays is not predetermined, while the size of the array is fixed but it can contain null elements in it and the null values are considered as zero. I need to get the sum of each cell into the corresponding index in the new array, whose size is logically same as other arrays.

I tried to depict the scenario as follows;

enter image description here

I have a solution with classical way of iteration but I end up with a very dirty implementation. I would be happy to see your solution for this problem (preferably with Stream api)

like image 560
Ad Infinitum Avatar asked Jul 03 '17 07:07

Ad Infinitum


2 Answers

A non-streams solution (because I don't think that an as-easily-understandable solution would be possible in streams):

int[] result = new int[n];  // n is the length of each array.
for (Integer[] array : arrays) {
  for (int i = 0; i < n; ++i) {
    // Increment the i-th element of the result by the i-th element of array.
    // Use 0 in place of null.
    result[i] += array[i] != null ? array[i].intValue() : 0;
    // or (suggested by shmosel)
    // if (array[i] != null) result[i] += array[i];
  }
}
like image 174
Andy Turner Avatar answered Oct 13 '22 23:10

Andy Turner


Here's a way to do it, inspired by shmosel's answer:

Integer[] result = new Integer[FIXED_SIZE];
Arrays.setAll(result, i -> list.stream().mapToInt(a -> a[i] == null ? 0 : a[i]).sum());

Another way would be with a custom collector:

static <T> Collector<T[], ?, T[]> reducingByColumn(
        T identity,
        BinaryOperator<T> operator,
        IntFunction<T[]> factory) {

    return Collector.of(
        HashMap<Integer, T>::new,
        (map, a) -> IntStream.range(0, a.length)
            .forEach(i -> map.merge(i, a[i] == null ? identity : a[i], operator)),
        (m1, m2) -> {
            m2.forEach((k, v) -> m1.merge(k, v, operator));
            return m1;
        },
        map -> map.values().toArray(factory.apply(map.size())));
}

This collector uses a map to accumulate intermediate results.

You could use it as follows:

Integer[] result = list.stream()
    .collect(reducingByColumn(0, Integer::sum, Integer[]::new));
like image 20
fps Avatar answered Oct 13 '22 21:10

fps