【问题标题】:The sum of the elements of an array [closed]数组元素的总和[关闭]
【发布时间】:2017-12-06 09:45:09
【问题描述】:

我对以下场景有疑问;

我在ArrayList 中有n-number 数组。数组的数量不是预先确定的,而数组的大小是固定的,但它可以包含空元素,空值被认为是零。我需要将每个单元格的总和放入新数组中的相应索引中,其大小在逻辑上与其他数组相同。

我试图将场景描述如下;

我有一个经典迭代方式的解决方案,但我最终得到了一个非常肮脏的实现。我很高兴看到您对这个问题的解决方案(最好使用Stream api

【问题讨论】:

  • 你能展示你的“肮脏的实现”吗?为什么这么脏? “干净”的实现会是什么样子?
  • @DatNguyen 我已经设计了“肮脏的实现”,但尚未实现。我的意思是使用嵌套的 for-each 循环来计算结果。
  • 如果预先知道所有数组的长度,我会想到一个简单的解决方案,其中包含两个 for 循环。这很“脏”吗?为什么你更喜欢Stream API?有什么要求?
  • @DatNguyen 要求不是我需要使用 Stream api 实现它,但直到现在,我一直看到使用 Stream api 的解决方案看起来更紧凑。这就是为什么,我更喜欢它。
  • 如果某个位置的所有元素都是null(例如,不是以12,9,null开头的数组,而是以null,null,null开头的数组?它们的总和是nullzero吗?跨度>

标签: java arrays java-stream


【解决方案1】:

这是一种方法,灵感来自shmosel's answer

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

另一种方法是使用自定义收集器:

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())));
}

此收集器使用映射来累积中间结果。

你可以这样使用它:

Integer[] result = list.stream()
    .collect(reducingByColumn(0, Integer::sum, Integer[]::new));

【讨论】:

  • 这样更好,并且方式更具可读性
  • 这太聪明了。感谢您的努力和回答。
【解决方案2】:

这是一个使用流的解决方案:

final int SIZE = ...
List<Integer[]> arrays = ...
Integer[] result = IntStream.range(0, SIZE)
        .map(i -> arrays.stream()
                .map(arr -> arr[i])
                .filter(Objects::nonNull)
                .mapToInt(Integer::intValue)
                .sum())
        .boxed()
        .toArray(Integer[]::new);

【讨论】:

  • 我只想说:这个解决方案很紧凑,但我不相信它是可读的。如果我在我正在阅读的代码中找到它,我当然得花点时间思考这个问题。
  • @shmosel OP 说“最好”。就像 OP 经常询问如何使用 regex 来解决没有 regex 更好地解决的问题(没有强烈证明这种偏好),展示替代方案是件好事。
  • IntStream.of(0, SIZE) 只会给你第一个和最后一个元素,并且会给你一个索引越界异常。
  • 它很好,紧凑且干净,但它真的很难阅读,但我更喜欢它而不是直接迭代
  • @Michael 谢谢,已修复。
【解决方案3】:

非流解决方案(因为我认为流中不可能有一个易于理解的解决方案):

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];
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-11
    • 2014-02-22
    • 2015-09-20
    • 2016-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多