Как объединить два FOR в один - PullRequest
3 голосов
/ 26 мая 2009

Это может быть глупо, но я хочу знать, если это возможно, давайте начнем с 5x5 матрицы

int[][] x = new int[5][5];      
Random rg = new Random();

теперь давайте заполним его псевдослучайной информацией

for(int i=0;i<5;i++){
    for(int j =0; j<5;j++){
        x[i][j] = rg.nextInt(); 
    }           
}

но как я могу сделать это правильно с одним синглом для?

for(int i=0, j=0; i<5; (j==5?i++, j=0:j++){
    x[i][j] = rg.nextInt();
}

это не работает: (

Ответы [ 7 ]

25 голосов
/ 26 мая 2009

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

for(int i = 0; i < 5 * 5; i++)
{
   int row = i / 5;
   int column = i % 5;
   x[row][column] = rg.nextInt();
}

Здесь использование / и% является классическим: здесь, когда вы перебираете индексы матрицы, деление используется, чтобы выяснить, в какой строке вы находитесь. Остаток (%) - это столбец.

Это великолепное искусство ASCII показывает, как одномерные индексы расположены в 2D матрице:

 0  1  2  3  4
 5  6  7  8  9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24

Должно быть понятно, что для любого значения в первой строке это значение, деленное на 5, является самим индексом строки, то есть они все равны 0.

8 голосов
/ 26 мая 2009

Вы действительно ничего не получите от этого. сохранить ваш код читабельным . на самом деле умножение и деление делаются более интенсивно, чем предлагается в цикле. (умножение деления и мода на самом деле сложный набор инструкций в АЛУ)

2 голосов
/ 26 мая 2009

Другой способ сделать это будет:

int i,j;
for (i=0,j=0; i<5 && j<5; i = (i==4 ? 0 : i+1), j = (i==4 ? j+1 : j))
{
   x[i][j] = rg.nextInt();
}

Хотя, я предпочитаю размотать решение.

0 голосов
/ 08 мая 2015

Кратчайшее решение

int i = 0,j=0;
 for(;j<5;j+=i==4?1:0,i++){
    if(i==5)
       i=0;
    x[j][i] = rg.nextInt();

  }
0 голосов
/ 26 мая 2009

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

0 голосов
/ 26 мая 2009

Мне стало любопытно и я сделал тест.

Для сервера Suns HotSpot 64 jvm в Linux и вложенные циклы, и развернутые циклы были более или менее одинаково быстрыми и почти такими же быстрыми, как итерации по линейному массиву [размер * размер]. Развернутый цикл, где infact медленнее, чем вложенный цикл, возможно потому, что он выполняет больше математики.

Однако в IBM 32-разрядной версии jdk 1.5 в Windows вложенный цикл работает более чем в 10 раз медленнее.

Хотя я не уверен, что в данном случае важен компилятор или jvm, более медленный тест был скомпилирован с использованием IBM RAD, который на год старше Eclipse 3.4

Таким образом, единственная причина, по которой ваш код может быть испорчен этими оптимизациями, заключается в том, что вы застряли на "предприимчивой" платформе со старым jvm и компилятором, и это действительно очень важно по времени.

0 голосов
/ 26 мая 2009
 int q = 5, r= 5;
 int [][] x = new int [q][r]

for(int i = 0, i < q * r, i++)
{
    int xaxis = i / q;
    int yaxis = i % r;

    x[xaxis][yaxis] = rg.nextInt();
}

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

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