Как выполнить поэлементное добавление n массивов, не используя просто для l oop in Java - PullRequest
0 голосов
/ 16 февраля 2020

Как следует из заголовка, мне интересно, как использовать Java для суммирования n (где n - произвольное число, большее 2) массивов вместе таким образом, чтобы масштабируется по мере увеличения n .

Вероятно, это проще всего объяснить на примере. Я использовал следующий код для получения 20 массивов длины 5.

int n = 20;
int k = 5;

Random rand = new Random();
ArrayList<Integer[]> tuplesList = new ArrayList<>();

for (int i = 0; i < n; i++) {
    Integer[] tuple = new Integer[k];
    Arrays.setAll(tuple, index -> rand.nextInt(30));
    tuplesList.set(i, tuple);
}

Теперь немного, я надеюсь, можно улучшить. Мой текущий метод сложения массивов поэлементно состоит в простом цикле прохождения каждого массива и добавлении их элементов к совокупной сумме.

int[] cumSum = new int[k];

for (Integer[] tup : tuplesList) {
    Arrays.setAll(cumSum, ind -> cumSum[ind] + tup[ind]);
}

System.out.println(Arrays.toString(cumSum));

Это, конечно, тривиально только с 20 массивами, но это может занять довольно много времени, если у нас было 1 000 000. Есть лучший способ сделать это? У меня есть векторизованный способ суммирования двух массивов поэлементно с использованием функции Arrays.setAll, но может ли это быть обобщено для сложения вместе n массивов? Обратите внимание, что нет никакого требования к тому, чтобы список массивов не хранился как ArrayList<Integer[]>, это именно то, к чему я впервые обратился.

PS Если кому-то нужны примеры чисел, вот что я получил, когда я пробежал свой сценарий:

[12, 20, 12, 22, 14]
[1, 10, 23, 9, 27]
[3, 2, 17, 24, 11]
[6, 11, 22, 5, 15]
[7, 26, 28, 27, 8]
[10, 23, 2, 15, 7]
[13, 5, 19, 3, 9]
[21, 23, 17, 16, 24]
[4, 20, 6, 14, 14]
[19, 4, 16, 24, 4]
[27, 14, 28, 0, 17]
[27, 20, 3, 8, 29]
[2, 21, 0, 24, 26]
[3, 2, 1, 23, 23]
[11, 11, 15, 26, 17]
[10, 26, 10, 8, 3]
[3, 27, 11, 13, 28]
[1, 29, 26, 3, 14]
[20, 1, 10, 29, 8]
[11, 25, 29, 28, 5]

Output:
[211, 320, 295, 321, 303]

1 Ответ

2 голосов
/ 16 февраля 2020

Если у вас есть 1 000 000 массивов, вы можете подумать об экономии памяти, используя вместо этого ArrayList<int[]>, или, возможно, int[][].

Если вы изменили значение на int[][], абсолютное большинство эффективный способ сделать это так:

static int[] sum(int[]... input) {
    int maxLen = 0;
    for (int[] arr : input)
        if (arr.length > maxLen)
            maxLen = arr.length;
    int[] sum = new int[maxLen];
    for (int[] arr : input)
        for (int i = 0; i < arr.length; i++)
            sum[i] += arr[i];
    return sum;
}

Первая половина, конечно, может быть заменена на maxLen = input[0].length, если она абсолютно гарантирует, что все массивы равной длины. Поскольку влияние этого кода на производительность минимально по сравнению со второй половиной кода, мы могли бы также сохранить первую половину даже с такой гарантией ( защитное программирование ).

Тест

System.out.println(Arrays.toString(sum(
        new int[] { 12, 20, 12, 22, 14 },
        new int[] { 1, 10, 23, 9, 27 },
        new int[] { 3, 2, 17, 24, 11 },
        new int[] { 6, 11, 22, 5, 15 },
        new int[] { 7, 26, 28, 27, 8 },
        new int[] { 10, 23, 2, 15, 7 },
        new int[] { 13, 5, 19, 3, 9 },
        new int[] { 21, 23, 17, 16, 24 },
        new int[] { 4, 20, 6, 14, 14 },
        new int[] { 19, 4, 16, 24, 4 },
        new int[] { 27, 14, 28, 0, 17 },
        new int[] { 27, 20, 3, 8, 29 },
        new int[] { 2, 21, 0, 24, 26 },
        new int[] { 3, 2, 1, 23, 23 },
        new int[] { 11, 11, 15, 26, 17 },
        new int[] { 10, 26, 10, 8, 3 },
        new int[] { 3, 27, 11, 13, 28 },
        new int[] { 1, 29, 26, 3, 14 },
        new int[] { 20, 1, 10, 29, 8 },
        new int[] { 11, 25, 29, 28, 5 }
)));

Выход

[211, 320, 295, 321, 303]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...