Как я могу сделать цикл для «n» измерений массива? - PullRequest
0 голосов
/ 13 октября 2019

Я пытаюсь создать метод, который суммирует потенциальные элементы и возвращает эту сумму из массива. Вот некоторые примеры входных данных, которые можно ожидать:

arraySum(new int[10]); // 10
arraySum(new int[2][5]); // 10
arraySum(new int[5][5][5]); // 125

Проблема в том, что я никогда не узнаю, с какими измерениями я работаю. До сих пор я обнаружил, что вызов String.valueOf(array) для массива возвращает строку, содержащую [ символов, хотя в массиве существует много измерений:

String.valueOf(new int[10]); // [I@hash_code
String.valueOf(new int[5][2]); // [[I@hash_code
String.valueOf(new int[5][5][5]); // [[[I@hash_code

Я могу использовать это, чтобы узнатьточное количество измерений, которые существуют для этого массива, выполнив String.valueOf(array).split("\\[").length - 1. Однако я не уверен, что я могу сделать с этой точки зрения.

public int arraySum(final Object array) {
    checkArgument(array.getClass().isArray()); // from com.google.common.base.Preconditions
    final int dimensions = String.valueOf(array).split("\\[").length - 1;
    int sum = 0;

    // somehow loop n-times over here to count up

    return sum;
}

Обычно при итерации многомерных массивов у вас будет несколько циклов внутри друг друга, но в моем случае мне потребуетсян-петли, которые я, очевидно, не могу жестко закодировать. Что я могу сделать?

Ответы [ 2 ]

1 голос
/ 13 октября 2019

Сделайте так:

public static int arraySum(final Object[] array) {
    if(array.length == 0) return 0;
    return array.length * ((array[0] instanceof Object[]) ? arraySum((Object[]) array[0]) : 1);
}

Вы также можете перегрузить этот метод для массивов примитивов. Вот как я бы сделал это с минимальным дублированием кода:

private static int doArraySum(Object array) {
    if(array == null || !array.getClass().isArray()) return 1;
    int length = Array.getLength(array);
    if(length == 0) return 0;
    return length * doArraySum(Array.get(array, 0));
}

public static int arraySum(Object[] array) {
    return doArraySum(array);
}

public static int arraySum(int[] array) {
    return doArraySum(array);
}

// other primitives

Если длина подмассивов может быть не одинаковой, вы должны использовать сложение вместо умножения:

private static int doArraySum(Object array) {
    if (array == null || !array.getClass().isArray()) return 1;
    return IntStream
            .range(0, Array.getLength(array))
            .map(i -> doArraySum(Array.get(array, i)))
            .sum();
}

Пример:

int[][] array = new int[2][];
array[0] = new int[2];
array[1] = new int[3];
arraySum(array); // 5
0 голосов
/ 13 октября 2019

Мое решение состояло в том, чтобы использовать цикл for для итерации по размерам и выполнения умножения длин:

public int arraySum(Object array) {
    int count = 1;      // necessary to prevent initial 0 multiplication
    int dim = ...;      // the dimensions of the array

    for (int i = 0; i < dim; ++i) {
        int len = Array.getLength(array);
        count *= len;

        if (len == 0) {
            break; // a length of 0 at any point means no potential items
        }

        array = Array.get(array, 0); // never fails, since len must be greater than 1 by this point
    }
}

Это дает мне потенциал длину, или иначе емкостьмассив для хранения определенного типа.

arraySum(new int[10]);          // 1 array with 10 ints, capacity 10 * 1 == 10
arraySum(new float[10][2]);     // 2 arrays with 10 floats, capacity of 2 * 10 == 20
arraySum(new CustomType[5][5]); // 5 arrays with 5 custom types, capacity 5 * 5 == 25
...