Конвертировать 2D зубчатый массив в правильный массив Java - PullRequest
0 голосов
/ 12 мая 2019

Я пытаюсь решить следующую проблему: у меня есть 2D зубчатый массив

[[1, 2], [1], [3, 4], [2, 3, 4]]

, который я хотел бы преобразовать в обычный 2D-массив. В настоящее время мне удалось получить это

[[1, 2, 0, 0], [1, 0, 0, 0], [3, 4, 0, 0], [2, 3, 4, 0]]

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

[[1, 2, 0, 0], [1, 0, 0, 0], [0, 0, 3, 4], [0, 2, 3, 4]]

Вот мой код, который создает этот массив, что не совсем то, что я хотел бы иметь:

[[1, 2, 0, 0], [1, 0, 0, 0], [3, 4, 0, 0], [2, 3, 4, 0]]
import java.util.*;

public class MultiDarrays {

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        System.out.println("Get number of two parameters: cyclists and bicycles: ");

        int c = sc.nextInt();
        int b = sc.nextInt();

        System.out.println("cyclists: " + c + " " + "bicycles: " + b);

        ArrayList<ArrayList<Integer>> multilist = new ArrayList<ArrayList<Integer>>();
        for (int i = 0; i < c; i++) {

            List<Integer> integers = new ArrayList<Integer>();
            int num = sc.nextInt();
            for (int j = 0; j < num; j++) {

                int elem = sc.nextInt();
                integers.add(elem);
            }
            multilist.add((ArrayList<Integer>) integers);
        }

        for (int i = 0; i < multilist.size(); i++) {
            System.out.println("Elements are: " + multilist.get(i));
        }
        sc.close();

        int[][] array = new int[multilist.size()][b];
        for (int i = 0; i < array.length; i++) {
            array[i] = new int[multilist.get(i).size()];
        }
        for (int i = 0; i < multilist.size(); i++) {
            for (int j = 0; j < multilist.get(i).size(); j++) {
                array[i][j] = multilist.get(i).get(j);
            }
        }

        System.out.println(Arrays.deepToString(array));

        int[][] full_array = new int[c][b];
        System.out.println(Arrays.deepToString(full_array));

        // copy elements from jagged to normal 2D array
        for (int i = 0; i < array.length; i++) {
            for (int j = 0; j < array[i].length; j++) {
                full_array[i][j] = array[i][j];
            }
        }

        System.out.println(Arrays.deepToString(full_array));
    }
}


Выход:

Get number of two parameters: cyclists and bicycles: 
4 4
cyclists: 4 bicycles: 4
2 1 2
1 1
2 3 4
3 2 3 4
Elements are: [1, 2]
Elements are: [1]
Elements are: [3, 4]
Elements are: [2, 3, 4]
[[1, 2], [1], [3, 4], [2, 3, 4]]
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
[[1, 2, 0, 0], [1, 0, 0, 0], [3, 4, 0, 0], [2, 3, 4, 0]]

Ответы [ 3 ]

1 голос
/ 12 мая 2019

Когда вы хотите записать значения в правильные индексы, которые они представляют, вы не можете просто сделать full_array[i][j] = array[i][j], потому что это игнорирует значение и просто «заполняет» массив, потому что j просто увеличивается нормально.
Что вам действительно нужно сделать, это использовать значение array[i][j] в качестве спецификации индекса:

full_array[i][array[i][j] - 1] = array[i][j];

Помните, что вам нужно уменьшить 1, потому что ваши значения начинаются с "1", а индексы массива - с "0".

Теперь результат выглядит так, как вы ожидаете:

[[1, 2, 0, 0], [1, 0, 0, 0], [0, 0, 3, 4], [0, 2, 3, 4]]


Теперь некоторые незначительные улучшения кода.

  1. ArrayList<ArrayList<Integer>> multilist = new ArrayList<ArrayList<Integer>>(); следует изменить на List<List<Integer>> multilist = new ArrayList<>();, потому что ваши типы должны быть объявлены как open , какими они могут быть, но как узкие , какими они должны быть. Вам нужен список, но на самом деле вам все равно, это ArrayList или, например, LinkedList. Также читайте Java - объявление типа интерфейса вместо класса .

  2. Этот каст multilist.add((ArrayList<Integer>) integers) не нужен. Вы должны были добавить, потому что вы (правильно) объявили integers как List<Integer> вместо ArrayList<Integer>, но так как мы исправили это в «1». тебе это больше не нужно.

  3. for (int i = 0; i < multilist.size(); i++) {
        System.out.println("Elements are: " + multilist.get(i));
    }
    

    можно заменить на расширенный цикл:

    for (List<Integer> integers : multilist) {
        System.out.println("Elements are: " + integers);
    }
    
0 голосов
/ 12 мая 2019

Я думаю, что вы не можете избежать двух циклов, но это все:

  1. Рассчитать ширину для соответствующего массива путем проверки первого элемента каждого подмассива
  2. Сделать копии в правильный массив.

Списки не участвуют.
Код с номерами вашего примера:

public static void main(String[] args) {
  int data[][]={{1, 2}, {1}, {3, 4}, {2, 3, 4}};
  int maxwidth=0;
  for(int line[]: data){
    maxwidth=Math.max(maxwidth, line[0]-1+line.length);
  }
  System.out.println(maxwidth);
  int proper[][]=new int[data.length][maxwidth];
  for(int i=0;i<data.length;i++){
    int line[]=data[i];
    System.arraycopy(line, 0, proper[i], line[0]-1, line.length);
  }

  for(int line[]: proper){
    for(int i=0;i<line.length-1;i++)
      System.out.print(line[i]+",");
    System.out.println(line[line.length-1]);
  }
}


Если @Tom прав насчет размещения отдельных элементов в отдельных местах (а не только в непрерывном «слоте», индексируемом первым элементом):
public static void main(String[] args) {
  int data[][]={{1, 2}, {1}, {3, 4}, {2, 3, 4}, {1, 5}};
  int max=0;
  for(int line[]: data)
    for(int val: line)
      max=Math.max(max,val);
  System.out.println(max);
  int proper[][]=new int[data.length][max];
  for(int i=0;i<data.length;i++){
    int line[]=data[i];
    for(int val: line)
      proper[i][val-1]=val;
  }

  for(int line[]: proper){
    for(int i=0;i<line.length-1;i++)
      System.out.print(line[i]+",");
    System.out.println(line[line.length-1]);
  }
}

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

0 голосов
/ 12 мая 2019

Существует несколько общих проблем с кодом в текущей форме.

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

Использование List на самом деле не обязательно. Когда ваши входные и выходные данные действительно являются int[] массивами, вы можете реализовать свои преобразования на их основе. Хотя во многих случаях List имеет свои преимущества, сомнительно, что вы можете добавить методы преобразования между int[] и List<Integer> и между int[][] и List<List<Integer>>.

В общем, когда у вас есть задача с многомерной структурой данных, такой как int[][] или List<List<Integer>>, и вы хотите выполнить операцию над внутренними элементами, полезно создать для этого специальный метод. В качестве упрощенного примера: когда у вас есть метод, такой как

static void addToEachElement2D(int array[][], int valueToAdd) { ... }

тогда этот метод может / должен быть реализован на основе метода

static void addToEachElement1D(int array[], int valueToAdd) { ... }

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


Однако вот одно из возможных решений данной задачи:

import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class MultiDarrays
{
    public static void main(String[] args)
    {
        int array[][] = new int[][]
        {
            { 1, 2 },
            { 1 },
            { 3, 4 },
            { 2, 3, 4 } 
        };

        int result[][] = unjag(array);    
        System.out.println(Arrays.deepToString(result));
    }

    private static int[][] unjag(int array[][])
    {
        int width = computeMaxValue(array);
        return unjag(array, width);
    }

    private static int[][] unjag(int array[][], int width)
    {
        int result[][] = new int[array.length][width];
        for (int i = 0; i < result.length; i++)
        {
            result[i] = unjag(array[i], width);
        }
        return result;
    }

    private static int[] unjag(int array[], int width)
    {
        int result[] = new int[width];
        for (int i = 0; i < array.length; i++)
        {
            int value = array[i];
            result[value - 1] = value;
        }
        return result;
    }

    private static int computeMaxValue(int array[][])
    {
        return Stream.of(array)
            .flatMapToInt(a -> IntStream.of(a))
            .max().getAsInt();
    }
}

Он вычисляет максимальное значение любого из внутренних массивов, которое также является шириной результирующего двумерного массива. Затем он «выравнивает» 2D-массив, «выравнивая» каждую строку входного массива, чтобы получить желаемую ширину.

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