【问题标题】:Java delimiter readerJava 分隔符阅读器
【发布时间】:2012-11-13 15:36:52
【问题描述】:

我有一个以冒号分隔的文本文件,其中包含结构化的分组数据。 People 组包含人名和年龄,用冒号分隔。如何解析文本并根据年龄分组?

结构如下:

Group.txt
Age:10:20:30:40:
Group:G1:10:G2:30:G3:20:G4:40:
People:Jack:10:Tom:30:Dick:20:Harry:10:Paul:10:Peter:20:
People:Mary:20:Lance:10:

我想显示如下内容:

G1 Jack Harry Paul Lance
G2 Dick Peter Marry
G3 Tom
G4

【问题讨论】:

  • 到目前为止您尝试过什么?如果您完全不知道从哪里开始,我建议您查看 javadocs 中的 String 类。 (docs.oracle.com/javase/7/docs/api/java/lang/String.html)
  • 我尝试过使用arraylist。和 line.split(":");但是使用这种方法我必须像 line(0), line(1), line(2) 等这样不好,因为一行中有 100 个输入?
  • 你的文本文件中有Group.txt吗?
  • Group.txt 为文件名,不包含在文本文件中
  • @newbieprogrammer.. 如果年龄在所有组之外怎么办?

标签: java delimiter


【解决方案1】:

我建议首先创建一个Map,其中包含相应年龄的所有组。

为此,您可以使用Regex 来获取左侧的alphanumeric 字符串,以及colon 右侧的digit,以获取以Group 开头的行。

我怀疑这些行来自您的文件。因此,首先您需要检查您的行是否以Group 开头。然后在该行上应用以下正则表达式:-

"([A-Za-z0-9]+):(\\d+)"  // Matches `G1:10`, `G2:30`, ...

然后将所有匹配的字符串的group 1group 2添加到Map<String, Integer>

现在,对于以People 开头的其他行,应用类似的正则表达式,但在colon 的左侧仅使用alphabetic characters,然后从已创建的@ 中获取特定年龄的group 987654336@.

"([A-Za-z]+):(\\d+)"  // Matches `John:22`

也许这会让你开始。


更新:

根据您的最新编辑,我建议创建一个具有 3 个属性的 Group 类:

class Group {
    private String groupName;
    private int age;
    private List<String> people;
}

而不是创建Map&lt;String, Integer&gt;,而是创建Map&lt;Integer, Group&gt;。你的工作会更轻松。 Integerage

因此,当您获得带有特定 agePerson 时,请从 Map 中获取该 age 的组对象,并使用该人更新该 group objectList&lt;String&gt;

请尝试一下,看看是否可以解决。

【讨论】:

  • 这种方法需要硬编码吗?因为人名可能不同 group.txt
  • 不,这不需要硬编码。您可以创建一个Map 并使用任何其他文件,并获取People。并为他们从地图中获取相应的组。
  • @newbieprogrammer.. 好。如果您遇到任何问题,请恢复。
  • @RomanC.. 你是谁?您已经在我的 3 个答案上背靠背发布了废话 cmets。似乎您出于某种我无法理解的原因开始了口水战。我什至不记得我曾经和你谈过。任何个人原因,我当然想知道。
【解决方案2】:

您可以使用StringTokenizer 拆分您的线路,然后创建一个实现Comparable Interface 的“People”类。

这些至少应该让你开始。

【讨论】:

    【解决方案3】:

    你可以split字符串:

    String[] items = row.split(":");
    
    if (items[0].equals("Age")) {
      // items[1] and onwards consists of Ages
    }
    if (items[0].equals("Group")) {
      // items[1] and onwards consists of group name/numbers
    }
    

    等等

    【讨论】:

      【解决方案4】:

      我会把这个任务分解成碎片。首先,找到所有组:

      /^Group:(G[0-9]+:[0-9]+)*/
      

      从该行获取第一个捕获组,在: 上拆分每个匹配项,然后您将每个组的名称映射到相应的年龄。

      接下来,与人类似的事情:

      /^People:([A-Za-z]+:[0-9]+)*/
      

      像以前一样进行匹配、分组和拆分,现在您可以将每个人映射到他或她的年龄。从那里,您所要做的就是为每个年龄组制作一个桶,按年龄对桶进行排序,然后将每个人放入适当的桶中。

      【讨论】:

      • 组和人如何联合起来排序?
      【解决方案5】:

      创建一个包含个人信息的新类。 (此方法可行,但为了保持简洁,打破了一系列良好实践。阅读 POJO 以了解有关如何将属性设为私有并添加访问器方法的更多详细信息(如果您愿意)。这是一个不同的讨论。

      public class Person { public String name; public int age; }
      

      然后您可以使用这个新类将人们的信息存储到您以后可以访问的列表中。

      当您遍历文件时,当您找到以People: 开头的行时,您可以使用以下代码对其进行解析:

          List<Person> people = new ArrayList<Person>();
          String str = "People:Mary:20:Lance:10:";  // Replace with the line you read from the file
          Pattern p = Pattern.compile("(?:([^:]*):(\\d*):)");
          Matcher m = p.matcher(str);
          while(m.find()) {
              for(int i=1; i<=m.groupCount(); i+=2) {
                  Person p = new Person();
                  p.name = m.group(i);
                  p.age = new Integer(m.group(i+1));
                  people.add(p);
              }
          }
      
      // At this point, all your people are store into the list.
      

      【讨论】:

      • 你不需要那个 for 循环。您的外部 while 循环就足够了。它将为您提供所有年龄的人。只需在您的 while 循环中打印 m.group(1)m.group(2)
      • 是的,我猜。我只是想使其通用,以防更多组添加到正则表达式中。
      • @mpvrivat 如何在 while 循环之外使用变量“age”?
      • 编辑了我的答案以进一步帮助您。我希望这会有所帮助。
      猜你喜欢
      • 2011-08-04
      • 2018-03-03
      • 2014-10-31
      • 2019-07-08
      • 1970-01-01
      • 2017-11-05
      • 1970-01-01
      • 1970-01-01
      • 2012-02-28
      相关资源
      最近更新 更多