Получить индексы 2D-массива из 1D

Итак, я пытаюсь перебрать все элементы в 2D-массиве, используя один цикл.

Вот где я:

public class Test {
    private static final String[][] key = {
        {"`", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=", "Backspace"}, // 0 - 13
        {"Tab", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "[", "]", "\\"},      // 0 - 13
        {"Caps", "A", "S", "D", "F", "G", "H", "J", "K", "L", ";", "'", "Enter"},       // 0 - 12
        {"Shift", "Z", "X", "C", "V", "B", "N", "M", ",", ".", "/", "\u2191"},          // 0 - 11
        {" ", "<", "\u2193", ">"}                                                       // 0 - 3
    };

    public static void main(String[] args) {
        final int totalLen = 57;
        String str = "";

        for (int i = 0, row = 0, col = 0; i < totalLen; ++i, ++col) {

            if (row < key.length && i % key[row].length >= key[row].length - 1) {
                ++row;
                col = 0;
                System.out.println(str);
                str = "";
            }

            if (row < key.length)
                str += col + " ";
        }
    }
}

Я прокомментировал диапазон индексов для каждой строки, которую должна вывести приведенная выше программа, но это не так, поскольку логика ошибочна. Какие-либо предложения?

Изменить: условие цикла должно оставаться прежним.


person Community    schedule 13.07.2014    source источник
comment
Какой смысл использовать магическое число (57) и настаивать на том, чтобы условие оставалось прежним? Плохая читабельность, ремонтопригодность... Что произойдет, если количество элементов НЕ 57? Ожидать исключения!?   -  person laune    schedule 13.07.2014
comment
Я объяснил причину в комментарии к одному из ответов. 57 — это не магическое число, это общее количество элементов в массиве. i используется как индекс для другого массива, который здесь не имеет значения.   -  person    schedule 13.07.2014
comment
@laune Редактировать: что произойдет, если количество элементов НЕ 57? Ожидать исключения!? Во-первых, вам нужно немного охладиться. Количество элементов вычисляется ранее, поэтому вероятность того, что оно не равно 57, исключена. Я удалил из примера ненужные детали.   -  person    schedule 13.07.2014
comment
Я просто поражен тем, что OP настойчиво поддерживает неестественное условие цикла, с конечным (totalLen), установленным на значение, рассчитанное ранее, то есть до времени компиляции.   -  person laune    schedule 14.07.2014
comment
Почему вы предполагаете, что это до времени компиляции? Раньше, чем раньше, он используется в этом методе. Я написал цикл для его подсчета, а затем сохранил его — во время выполнения. Мне не нужно было загромождать вопрос, включая этот цикл. Я просто поражен твоей зацикленностью на условии.   -  person    schedule 15.07.2014
comment
Я поражен настойчивостью этого условия цикла, потому что я не вижу ни его необходимости, ни его преимущества.   -  person laune    schedule 15.07.2014


Ответы (3)


Попробуйте это решение, оно использует один цикл while и то же условие цикла из вопроса (по запросу):

String str = "";
int row = 0, col = 0;
int i = 0, totalLen = 57;

while (i < totalLen) {
    if (col < key[row].length) {
        str += col++ + " ";
        i++;
    } else {
        System.out.println(str);
        str = "";
        row++;
        col = 0;
    }
}
System.out.println(str); // prints the last line

В качестве альтернативы, если вы предпочитаете использовать цикл for:

String str = "";
int totalLen = 57;

for (int i = 0, row = 0, col = 0; i < totalLen; i++) {
    str += col++ + " ";
    if (col == key[row].length) {
        row++;
        col = 0;
        System.out.println(str);
        str = "";
    }
}

Любой фрагмент выведет на консоль следующий вывод:

0 1 2 3 4 5 6 7 8 9 10 11 12 13 
0 1 2 3 4 5 6 7 8 9 10 11 12 13 
0 1 2 3 4 5 6 7 8 9 10 11 12 
0 1 2 3 4 5 6 7 8 9 10 11 
0 1 2 3
person Óscar López    schedule 13.07.2014

Вы должны иметь возможность сделать это с двумя переменными row и col, где col увеличивается в заголовке цикла, а row увеличивается условно в теле цикла:

for (int row =0, col = 0 ; row != key.length ; col++) {
    System.out.println(row + " " + col);
    if (col == key[row].length-1) {
        row++;
        col = 0;
    }
}

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

Вы также можете добавить i и остановиться, когда достигнете totalLen:

for (int row =0, col = 0, i = 0 ; i != totalLen ; col++, i++) {
    System.out.println(row + " " + col);
    if (col == key[row].length-1) {
        row++;
        col = 0;
    }
}

Однако это более хрупко, потому что вы получаете зависимость от правильного вычисления totalLen.

person Sergey Kalinichenko    schedule 13.07.2014
comment
Оба решения выводят неверные результаты, код OP намеревается создавать значения col для каждой строки, см. Мой ответ. - person Óscar López; 13.07.2014

Хорошо, я попытался сохранить ваше условие цикла как есть... но я не использую каждый параметр. В любом случае должно работать:

for (int i = 0, row = 0, col = 0; i < totalLen; ++i, ++col) {
    System.out.println("row " + row + ", col " + col);
    // what ever you want to do with your loop, do it here
    // before altering the row and col parameters

    if (col == key[row].length-1) {
        col = -1;   // if end of the row, set col to -1, it will be incremented in the next loop
        row++;
        if(row==key.length){
            break;
        }
    }
}

в основном это почти то же самое, что сделал @dasblinkenlight — только я ввел условие break, когда переменная row достигает длины массива key. Вы также можете проверить if(i==totalLen), но лично я считаю более надежным проверить длину массива.

person GameDroids    schedule 13.07.2014
comment
@ user2570380, вы правы, я поправил. Извините - person GameDroids; 14.07.2014