繁体   English   中英

将2D锯齿状数组转换为适当的Java数组

[英]Convert 2D jagged array to proper array Java

我正在尝试解决以下问题:我有一个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]]

当您想将值写入它们所代表的正确索引时,则不能只执行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<>(); ,因为应将您的类型声明为尽可能开放 ,但应根据需要声明为狭窄 您需要一个列表,但实际上并不关心它们是ArrayList还是例如LinkedList。 另请阅读从接口类型而不是类声明Java

  2. multilist.add((ArrayList<Integer>) integers)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); } 

当前表单中的代码存在一些一般性问题。

测试它很烦人,因为您总是必须输入输入值。 一次定义它们,以便您可以快速轻松地测试代码。

使用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数组的宽度。 然后,通过“取消对齐”输入数组的每一行以使其具有所需的宽度,从而“取消对齐” 2D数组。

我认为您无法避免两个循环,仅此而已:

  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]); } } 

我真的不能说出您的意思是什么方法,示例编号在这里非常无济于事。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM