【问题标题】:What is the most efficient way to create a 2d string array of initally repetitive data?创建初始重复数据的二维字符串数组的最有效方法是什么?
【发布时间】:2021-05-29 06:14:31
【问题描述】:

在 Python 中,通常要定义所述游戏板,我会使用以下代码:

board = [['0','0','0','0','0','0','0','0','0','0'] for i in range(10)]

但是,到目前为止,我能够找到产生相同结果的唯一方法是使用 Java:

public static String[][] board = {
        {"0","0","0","0","0","0","0","0","0","0"},
        {"0","0","0","0","0","0","0","0","0","0"},
        {"0","0","0","0","0","0","0","0","0","0"},
        {"0","0","0","0","0","0","0","0","0","0"},
        {"0","0","0","0","0","0","0","0","0","0"},
        {"0","0","0","0","0","0","0","0","0","0"},
        {"0","0","0","0","0","0","0","0","0","0"},
        {"0","0","0","0","0","0","0","0","0","0"},
        {"0","0","0","0","0","0","0","0","0","0"},
        {"0","0","0","0","0","0","0","0","0","0"}};

当然必须有更有效的方法来做到这一点。我知道如果它是整数,我可以有效地做到这一点,但考虑到这种情况,它必须是字符串。我原以为 for 循环也可以应用,但我似乎找不到合适的语法;也许它不适用于Java。有什么建议吗?

【问题讨论】:

    标签: java arrays string multidimensional-array


    【解决方案1】:

    您可以遍历每一行并使用Arrays.fill

    public static String[][] board = new String[rows][cols];
    static {
        for (String[] row : board) Arrays.fill(row, "0");
    }
    

    Demo

    【讨论】:

      【解决方案2】:

      您可以使用嵌套的for 循环来创建 10 行和 10 列。因此,在第一个循环(创建一个“行”)中,您需要添加另一个循环来填充“列”。

      String[][] board = new String[10][10];
      
      // 10 rows
      for (int i = 0; i < 10; i++) {
          // 10 columns
          for (int j = 0; j < 10; j++) {
              // Set the value of this row/column
              board[i][j] = "0";
          }
      }
      

      这显然不如 Python 的单行解决方案优雅,但它可以满足您的需求。

      还有其他方法可以做到这一点(例如在每个循环中将一个完整的 10 位数组添加到 board 数组),但我发现这对于可扩展性和可读性来说是最好的。


      为了更清楚起见,如果您将来可能需要更改行数或列数,最好将这些值移动到变量中并改用它们:

      int rows = 10;
      int cols = 10;
      
      String[][] board = new String[rows][cols];
      
      for (int i = 0; i < rows; i++) {
          for (int j = 0; j < cols; i++) {
              board[i][j] = "0";
          }
      }
      

      这样你只需要更新变量而不是修改for循环和数组声明。

      【讨论】:

      • 哦,我明白了。所以,我将板定义为 10x10,然后返回并将值重置为“0”,允许它们用作字符串......对吗?
      • 假设您提前知道确切的尺寸,是的。不过,到目前为止,这里的其他答案在代码行方面可能更有效。这真的取决于什么对你来说更具可读性。
      • 它始终是相同的确切尺寸是的。唯一要改变的是他们的价值观。可读性在这里有些重要,我相信您的解决方案似乎是我见过的最好的。非常感谢您的解决方案;事实证明,在 Python 和 Java 之间转换很困难。
      • 这基本上是教科书的迭代方法。如果您打算使用嵌套的 for 循环,使用经典的迭代样式直接对数组值进行操作,那么这将尽可能简单明了。
      • @M.Justin 是的,这正是我想要的。这是将被审查的代码,不幸的是,我不得不向没有经验的人逐行解释,所以这可能是我能找到的最佳解决方案。
      【解决方案3】:

      你可以这样做。因为Strings 是不可变的,所以在这里使用clone() 是安全的。感谢@iota 推荐setAll

      int n = 10;
      String[][] arr = new String[n][n];
      Arrays.fill(arr[0], "0");
      Arrays.setAll(arr, i->arr[0].clone());
      
      
      for(String[] a : arr) {
          System.out.println(Arrays.toString(a));
      }
      

      打印

      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
      

      【讨论】:

      • 试试arr[1][2] = "2"。该数组中恰好有两个实例String[10]:第一个子数组(原始)和第二个子数组(克隆)重复直到结束(字符串是不可变的,(子)数组不是)
      • @WJS 你可以使用Arrays.setAll来避免这个问题:String[] row = arr[0].clone();Arrays.setAll(arr, i -&gt; row.clone());
      • @WJS 没问题。
      【解决方案4】:

      以下是基于stream 的解决方案,该解决方案使用函数式样式而非迭代式样式:

      return Stream.generate(() -> 
                      Collections.nCopies(10, "0").toArray(String[]::new))
              .limit(10)
              .toArray(String[][]::new);
      

      请注意,根据可读性等要求,可能会认为经典的迭代样式更可取。

      说明

      Collections.nCopies(10, "0") 创建一个包含 10 个 "0" 值的 List&lt;String&gt;。使用Collection.toArray(IntFunction) 将其转换为String 数组。这需要一个IntFunction,它会生成一个给定长度的数组。 String[]::new 是一个 constructor lambda,它实现了 IntFunction&lt;String[]&gt;,创建了一个给定长度的数组。

      Stream.generate 通过调用给定的Supplier 创建每个元素的无限流。在这种情况下,供应商创建了前面提到的 10 元素长列表,结果是 Stream&lt;String[]&gt;。使用了生成器,而不是 Collections.nCopies,因为 String[][] 中的每个 String[] 都需要是不同的对象。

      无限流仅限于使用Stream.limit(10) 的十个元素。

      最后,使用Stream.toArray(IntFunction)Stream&lt;String[]&gt; 收集到String[][] 中,其工作方式与已经描述的Collection.toArray 方法相同。

      【讨论】:

        【解决方案5】:

        这是 for 循环和手动创建一行单元格的混合体。

        String[][] board = new String[10][];
        for (int i = 0; i < 10; i++) {
            board[i] = new String[]{"0","0","0","0","0","0","0","0","0","0"};
        }
        

        【讨论】:

          【解决方案6】:

          String#repeat 从 11 开始

          String[][] board = new String[10][];
          
          1. Arrays.setAll - 每行重复 0 十次并拆分为一个数组:
            Arrays.setAll(board, i -> "0".repeat(10).split(""));
            
          2. Arrays.fill - 在这种情况下,结果是一样的:
            Arrays.fill(board, "0".repeat(10).split(""));
            

          输出:

          Arrays.stream(board).map(Arrays::toString).forEach(System.out::println);
          
          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
          

          另见:How can I fill this 2D array with X characters?

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-08-10
            • 1970-01-01
            • 2020-12-10
            • 2011-06-04
            • 1970-01-01
            • 1970-01-01
            • 2016-11-12
            • 1970-01-01
            相关资源
            最近更新 更多