Итерация по массиву 2d-строк для отображения всех комбинаций данного массива

#java #arrays #multidimensional-array #iteration #nested-loops

#java #массивы #многомерный массив #итерация #вложенные циклы

Вопрос:

Я хочу попробовать реализовать способ перебора всех возможных вариантов значений внутри 2d-массива.

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

 String[] pos = {"1", "2", "3", "4", "5"};
String[] color = {"green", "red", "white", "black", "blue"};
String[] cars = {"xtrail", "camry", "civic", "accent", "barina"};
String[] home = {"canada", "british", "french", "chinese", "indian"};
String[] location = {"sydney", "goldcoast", "newcastle", "tamworth", "portmaq"};
String[] time = {"5am", "6am", "7am", "8am", "9am"};
  

а затем повторение с использованием вложенных циклов for:

 for (int a = 0; a < 5; a  ) {
    for (int b = 0; b < 5; b  ) {
        for (int c = 0; c < 5; c  ) {
            for (int d = 0; d < 5; d  ) {
                for (int e = 0; e < 5; e  ) {
                    for (int f = 0; f < 5; f  ) {
                        String[] ans = {pos[a], color[b], cars[c],
                                home[d], location[e], time[f]};
                    }
                }
            }
        }
    }
}
  

Где ans массив содержит текущую итерацию возможного car.

Можно ли это сделать с использованием 2d-массива вместо 5 разных 1d-массивов:

 String[][] travel = {
        {"1 ", "green ", "xtrail ", "canada ", "sydney ", "5am"},
        {"2 ", "red ", "camry ", "british ", "goldcoast ", "6am"},
        {"3 ", "white ", "civic ", "french", "newcastle ", "7am"},
        {"4 ", "black ", "accent ", "chinese ", "tamworth ", "8am"},
        {"5 ", "blue ", "barina ", "indian ", "portmaq ", "9am"}};
  

Для достижения того же результата, что и ans только со всеми возможными комбинациями из 5 машин одновременно с 2d-массивом?

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

Ответ №1:

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

 import java.util.*;

class test {
    static String[][] travel = { 
        { "1 ", "2 ", "3 ", "4 ", "5 " }, 
        { "green ", "red ", "white ", "black ", "blue " },
        { "xtrail ", "camry ", "civic ", "accent ", "barina " },
        { "canada ", "british ", "french", "chinese ", "indian " },
        { "sydney ", "goldcoast ", "newcastle ", "tamworth ", "portmaq " }, 
        { "5am", "6am", "7am", "8am", "9am" } 
    };

    public static void generate(String travel[][]) {
        _generate(travel, 0, new String[travel.length]);
    }

    private static void _generate(String travel[][], int level, String ans[]) {
        for (int i = 0; i < travel[level].length; i  ) {
            ans[level] = travel[level][i];
            if (level   1 == travel.length) {
                /* consume the answer here */
                System.out.println(Arrays.toString(ans));
            } else {
                _generate(travel, level   1, ans);
            }
        }
    }

    /* usage */
    public static void main(String a[]) {
        generate(travel);
    }
}
  

Более общим ответом было бы использовать пользовательский интерфейс и обобщить это решение

 import java.util.*;
import java.util.function.*;

class test {
    static String[][] travel = { 
        { "1 ", "2 ", "3 ", "4 ", "5 " }, 
        { "green ", "red ", "white ", "black ", "blue " },
        { "xtrail ", "camry ", "civic ", "accent ", "barina " },
        { "canada ", "british ", "french", "chinese ", "indian " },
        { "sydney ", "goldcoast ", "newcastle ", "tamworth ", "portmaq " }, 
        { "5am", "6am", "7am", "8am", "9am" } 
    };

    public static void generate(String travel[][], Consumer<String[]> f) {
        _generate(travel, 0, new String[travel.length], f);
    }

    private static void _generate(String travel[][], int level, String ans[], Consumer<String[]> f) {
        for (int i = 0; i < travel[level].length; i  ) {
            ans[level] = travel[level][i];
            if (level   1 == travel.length) {
                f.accept(ans);
            } else {
                _generate(travel, level   1, ans, f);
            }
        }
    }

    /* usage */
    public static void main(String a[]) {
        generate(travel, x -> System.out.println(Arrays.toString(x)));
    }
}
  

Ответ №2:

Было бы проще решить это, введя ваш 2D-массив таким образом:

 String[][] travel = {
        { "1", "2", "3" },
        { "green", "red", "white" },
        { "xtrail", "camry", "civic" }
};
  

Решение для 2D-массива фиксированного размера (я уменьшил размер до 3 для целей пояснения. Способ ее решения не меняется) является:

 for (String str : travel[0]) {
    for (String str1 : travel[1]) {
        for (String str2 : travel[2]) {
            String[] ans = { str, str1, str2 };
            System.out.println(Arrays.asList(ans));
        }
    }
}
  

Для общего решения вы можете создать рекурсивную функцию, как показано ниже:

 static void addOps(String[] ans, String[][] travel, int i) {
    if (i == travel.length) {
        System.out.println(Arrays.asList(ans));
    } else if (i < travel.length) {
        for (String str : travel[i]) {
            ans[i] = str;
            addOps(ans, travel, i 1);
        }
    }
}
  

затем вызовите его из метода main:

 String[] ans = new String[travel.length];
addOps(ans, travel, 0);
  

Ответ №3:

Это можно решить, найдя перестановки для каждого столбца по отношению к строке и сохранив его в массиве 1D outputRow .

Это достигается рекурсивным вызовом print функции, как показано ниже:

 public class StackOverflow 
{    
    public static void main(String[] args) 
    {
        String[][] travel = 
        {     
                { "1 ", "green ", "xtrail ", "canada ", "sydney ", "5am" },
                { "2 ", "red ", "camry ", "british ", "goldcoast ", "6am" },
                { "3 ", "white ", "civic ", "french", "newcastle ", "7am" },
                { "4 ", "black ", "accent ", "chinese ", "tamworth ", "8am" },
                { "5 ", "blue ", "barina ", "indian ", "portmaq ", "9am" } 
            
        };
            
        int row = travel.length;
        int col = travel[0].length;
        
        String[] outputRow = new String[col];
        print(0, row, col, travel, outputRow);
 
     }

     static void print(int j, int row, int col, String[][] first, String[] outputRow) 
     {
       for (int i = 0; i < row; i  ) 
       {
           outputRow[j] = first[i][j];

           //Recursively continue to populate outputRow until we reach the last column i.e. (j == col -1)
           if (j < col - 1) 
               print(j   1, row, col, first, outputRow);               

           // We have reached the last column (j == col -1), so we print the current permutation.
           if (j == col - 1) 
           {
               for (int k = 0; k < col; k  )
                   System.out.print(" "   outputRow[k]);                   
               System.out.println();                   
           }
        }
     }
}
  
  1. Здесь мы создаем 1D-массив строк с именем outputRow и передаем его в качестве одного из параметров print функции.
  2. print функция обрабатывает один столбец за рекурсию и продолжает сохранять его в outputRow массиве.
  3. Обработка столбца начинается с j == 0 , который является первым аргументом, переданным print функции.
  4. Когда он достигает последнего столбца, т. Е. j == col - 1; , печатается текущая перестановка строк.

Вышеуказанные 4 точки представляют 1 цикл рекурсии для каждой уникальной перестановки в строке. Этот цикл повторяется для всех строк в 2D-массиве.