【问题标题】:Processing range of lines in a 2d array or file处理二维数组或文件中的行范围
【发布时间】:2016-08-07 23:19:47
【问题描述】:

我对编程很陌生。我正在自学,我正在使用的书中的例子太简单了,所以我正在努力做一些更难的事情。彩票是我的爱好之一,我认为我选择的问题将使我更容易学习 Java。

这个程序计算基诺中的频率(从 1 到 70 的每个数字出现在我的 txt 文件中的次数),这是一种彩票(在基诺中,抽奖由 70 个数字中的 20 个数字组成,而不是普遍的 6 个数字) 49)。

我想计算的频率不是整个 txt 文件,而是其中的一部分,例如,如果文件有 x 行,我只想要 x-5 和 x-10 之间的行,像这样.我不知道我的文件中的行数,也许是数千,但它总是有 20 列。

该程序对整个文件运行良好,但在尝试仅处理其中的一部分时遇到了麻烦。我认为我应该将文件读入二维数组,然后我可以处理我想要的行。我很难将每一行转换成矩阵。我已经阅读了所有关于将文件读入二维数组但无法使其工作的帖子。

以下是我一个多星期以来所做的众多尝试之一

public static void main(String args[]) {

    int[][] matricea = new int [30][40];
    int x=0, y=0;

    try { 
        BufferedReader reader = new BufferedReader(
            new FileReader("C:\\keno.txt")
        ); 

        int[] numbers = new int[72];  //each keno draw has 70 numbers

        for (int i = 0; i < 71; i++ ){ 
            numbers[i] = 0;      
        } 

        int k=0;    // k counts the lines 
        String draw; 

        while ( (draw = reader.readLine()) != null ) { 

            String[] pieces = draw.split(" +"); 
            k++;

            for (String str : pieces) {
                int str_int = Integer.parseInt(str);
                matricea[x][y] = str_int;
                System.out.print(matricea [x][y] + " ");
                y = y + 1;
            }

            x = x + 1;
            System.out.println(" "); 
        }

        for (int j = 1; j <= 20; j++) { 
            int drawnNumber = Integer.parseInt(pieces[j]); 
            numbers[drawnNumber]++; 
        } 

        System.out.println(" nr. of lines is  " + k);
        reader.close(); 

        for (int i = 0; i < 71; i++) { 
            System.out.println(i + ": " + numbers[i]); 
        } 

    } catch (Exception e) { 
        System.out.println("There was a problem opening and processing the file."); 
    } 

}

【问题讨论】:

  • 如果您需要帮助,您至少应该花时间很好地格式化您的问题,而不是一堆文字。您还应该正确缩进您的代码。因为它非常难以阅读,并且会被大多数人忽略
  • 文件格式如何?
  • 对不起。这是我的第一篇文章。我会让代码看起来更好。文件是txt。
  • 在美国,一场基诺游戏是从 80 中抽出 20 个号码。玩家可以选择 1 到 7 个号码,他希望这些号码包含在抽出的 20 个号码中。一个数字命中的几率是 50%。其他多号选择的几率小于 50%。请更全面地描述您的基诺游戏。
  • 在加拿大安大略省,平局是 70 分中的 20 分。我不想计算赔率或其他东西。只是文件中某个部分的频率,其中包含以前绘制的数字。

标签: java arrays file


【解决方案1】:

格式化和改进当前代码

我将展示如何解决您的问题,但首先我想指出您的代码中的一些内容,这些内容可以通过某些格式进行改进,或者可能是不必要的。

只是为了帮助您提高编码技能,可读性非常重要! :)

别忘了,一致性是关键!如果您比更常见的样式或首选样式更喜欢一种样式,那么只要您在整个编码过程中使用它就可以了。不要在两种样式之间切换。

如果您不介意阅读这些 cmets,可以在我的答案底部找到解决方案。请注意,您的原始代码在我的解决方案中会有所不同,因为我已将其格式化为对我来说最易读。


变量声明中的间距

原始代码

int[][] matricea = new int [30][40];
int x=0, y=0;

间距修改

int[][] matricea = new int[30][40];
int x = 0, y = 0;

注意int[30][40] 之间删除的空格,以及变量和初始化之间添加的空格,即-x=0 => x = 0


初始化一个 int 数组以包含所有的 0

原始代码

int[] numbers = new int[72];  //each keno draw has 70 numbers

for (int i = 0; i < 71; i++ ){ 
    numbers[i] = 0;      
} 

int[] numbers = new int[72];  //each keno draw has 70 numbers

您不必将每个值都设置为0,Java 会为您完成。事实上,Java 对所有类型都有默认值或空值。 感谢 Debosmit Ray!

我不会讨论这个案例的例外情况,或者何时、为什么或如何,您可以在 this post 中阅读相关内容,并密切关注 Aniket Thakur 的回答。

但是,如果只有 70 种可能性,为什么还要有一个大小为 72 的数组呢?


选择变量名

原始代码

int k=0;     // k counts the lines

int numLines = 0;

您应该始终使变量名称对其目的有意义。如果您必须使用 k counts the lines 之类的评论来描述变量的用途,请考虑是否可以使用更好的名称。


功能化代码

原始代码

 while ( (draw = reader.readLine()) != null ) { 

      String[] pieces = draw.split(" +"); 
      k++;
                    
      for (String str : pieces) {
           int str_int = Integer.parseInt(str);
           matricea[x][y] = str_int;
           System.out.print(matricea [x][y] + " ");
           y = y + 1;
      }
                
      x = x + 1;
      System.out.println(" "); 
 }

while ( (draw = reader.readLine()) != null ) { 
    processLine(draw);
}

当然,您必须创建方法processLine(String line),但这并不难。它只是把你拥有的东西转移到一个单独的方法中。

原始代码的while循环非常繁忙和混乱,但使用后一个选项使目的明确,代码干净。

当然,每种情况都不同,您可能会发现仅将部分代码删除到方法中会是更好的解决方案。随便玩玩看看有什么意义。


错误!

原始代码

for (int j = 1; j <= 20; j++) { 
    int drawnNumber = Integer.parseInt(pieces[j]); 
    numbers[drawnNumber]++; 
} 

这段代码不应该工作,因为pieces 是在它上面的while 循环中声明的,并且是上面循环的局部变量。此 for 循环超出了pieces 所在的范围

我会告诉你如何修复它,但我不确定代码应该做什么。只要让我知道它的目的是什么,我就会为您提供解决方案。


格式化后!

这是应用我上面的 cmets 后代码的样子。我已将 cmets 添加到我已更改的部分。

public static void main(String args[]) {

    try { 
        doKenoStuff();
    } catch(IOException e) {
        System.out.println("There was a problem opening and processing the file.");
    }
    
}

public static void doKenoStuff() throws IOException {
    BufferedReader reader = new BufferedReader(
            new FileReader("C:\\keno.txt")
    ); 
    
    int[][] matricea = new int[30][40];
    int[] numbers = new int[72];  //each keno draw has 70 numbers
    
    // We can clean up our loop condition by removing
    // the assignment (draw = reader.readLine) from it.
    // Just make sure draw doesn't begin as null.
    String draw = "";
    int row;
    
    for(row = 0; draw != null; row++) {
        draw = reader.readLine();
        
        // We read a line from the file, then send it
        // to extractLineData which will collect the info
        // from each column, and update matricea and numbers
        extractLineData(draw, row, matricea, numbers);
    }
    
    System.out.println("Number of lines: " + row);
    System.out.println("Each number's drawing stats:");
    
    for (int i = 0; i < 71; i++) { 
        System.out.println(i + ": " + numbers[i]); 
    } 
    
    reader.close(); 
    
}

public static void extractLineData(String line, int row, int[][] matrix, int[] numbers) {
    String linePieces = line.split(" +");
    
    for(int column = 0; column < linePieces.length; column++) {
        int number = Integer.parseInt(linePieces[column]);
        matrix[row][column] = number;
        numbers[number]++;
    }
}

解决方案

注意:我并不完美,我的代码也不完美。我并不是说我所建议的只是唯一 的方式来做到这一点。它肯定可以改进,但这是一个开始。您应该采用我的解决方案,看看如何自己改进它。
您能发现哪些可以用更简洁、更快或更好的方式编写代码?

那么,我们该如何解决这个问题呢?

我们有一个从文件开头到结尾读取的方法,它记录在matricea 中找到的数据。

一个快速简单的解决方案是简单地使该方法接受两个参数,一个起始行号和一个结束行号。

public static void doKenoStuff(int start, int end) throws IOException {

然后我们简单地做一个循环来跳过起跑线!就这么简单!!!

for(int i = 0; i < start - 1; i++) {
    reader.readLine();
}

不要忘记,我们可能不再需要大 30 行 matricea 为 30 行。我们可以将其缩小到end - start + 1。这样,如果用户想从第 45 行读取到第 45 行,我们只需要 matricea 中的 45 - 45 + 1 = 1 行。

int[][] matricea = new int[end - start + 1][40];

我们需要添加的最后一件事是行读取循环中的一个条件,它可以防止我们越过结束行。

for(row = 0; draw != null, row <= end; row++) {

你有它。就这么简单!


完整的解决方案

public static void main(String args[]) {
    int start = 7, end = 18;

    try { 
        doKenoStuff(start, end);
    } catch(IOException e) {
        System.out.println("There was a problem opening and processing the file.");
    }
}

public static void doKenoStuff(int start, int end) throws IOException {
    BufferedReader reader = new BufferedReader(
            new FileReader("C:\\keno.txt")
    ); 
    
    int[][] matricea = new int[end - start + 1][40];
    int[] numbers = new int[72];  //each keno draw has 70 numbers
    
    for(int i = 0; i < start - 1; i++) {
        reader.readLine();
    }
    
    String draw = "";
    int row;
    
    for(row = 0; draw != null, row <= end; row++) {
        draw = reader.readLine();
        extractLineData(draw, row, matricea, numbers);
    }
    
    System.out.println("Number of lines: " + row);
    System.out.println("Each number's drawing stats:");
    
    for (int i = 0; i < 71; i++) { 
        System.out.println(i + ": " + numbers[i]); 
    } 
    
    reader.close(); 
}

public static void extractLineData(String line, int row, int[][] matrix, int[] numbers) {
    String linePieces = line.split(" +");
    
    for(int column = 0; column < linePieces.length; column++) {
        try {
            int number = Integer.parseInt(linePieces[column]);
            matrix[row][column] = number;
            numbers[number]++;
        } catch (NumberFormatException) {
            // You don't have to do anything in this block, but
            // you can print out what input gave the exception if you want.
            System.out.println("Bad input: \"" + linePieces[column] + "\"");
        }
    }
}
        

【讨论】:

  • 对于任何读者,我在完成之前不小心发布了我的答案。我现在正在解决方案中进行编辑。
  • j 是列计数器。然后该行上的每个数字都放入数组 numbers。有时在文件中第 20 列之后的内容我不想在文件中包含它们
  • 感谢以上建议
  • Initializing an int array to contain all 0's 不需要。 int 原语的空值为 0。可能希望将其添加到部分
  • 图书馆关门了,等我回家再发帖。到目前为止,我的 Netbeans 给了我一些错误,而且我对您编写的代码一点也不熟悉。可能缺少一些昏迷或其他东西。我会及时通知你。
猜你喜欢
  • 1970-01-01
  • 2014-09-25
  • 2014-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多