【问题标题】:Sorting multiple strings into an element将多个字符串排序到一个元素中
【发布时间】:2013-09-25 20:05:42
【问题描述】:

以下是非常大文件的一小部分摘录。

我正在寻找一种将每个名称和值(在 Name(x)Value(x) 行上)放入数组元素的方法或 List 类型,两者之间有一个“=”。

即让每个元素看起来像“'name' = 'value'”。

[Device|EEP_FEATUREKOI_HFS_Max|Kostia]
--------------------------------
Name(1) = partHeader_A01
Value(1) = 0x10
Desc(1) = (Address 0x000) Article No. / P.C.B No Byte 1
Name(2) = partHeader_A02
Value(2) = 0x9
Desc(2) = (Address 0x001) Article No. / P.C.B No Byte 2
Name(3) = partHeader_A03
Value(3) = 0x95
Desc(3) = (Address 0x002) Article No. / P.C.B No Byte 3
Name(4) = partHeader_A04
Value(4) = 0x38
Desc(4) = (Address 0x003) Article No. / P.C.B No Byte 4
----------------------------------
Name(12) = AdrIctPcbTestDate_Day
Value(12) = 0xFF
Desc(12) = (Address 0x00B) Test Date : Day
---------------------------------
Name(13) = AdrIctPcbTestDate_Month
Value(13) = 0xFF
Desc(13) = (Address 0x00C) Test Date : Month
---------------------------------
Name(14) = AdrIctPcbTestTime_Hour
Value(14) = 0xFF
Desc(14) = (Address 0x00D) Test Time : Hour
---------------------------------
Name(15) = AdrIctPcbTesTime_Minute
Value(15) = 0xFF
Desc(15) = (Address 0x00E) Test Time : Minute

到目前为止,我可以获得名称和值。我的问题是,当一个部分有超过 1 个字节时(在名称中用“_”表示),我需要将所有字节值放在同一个元素中,只有一个名称。

我想不出正确的算法来让它正常工作。

即对于 partHeaderArtLK_A01partHeaderArtLK_A04,而不是有

partHeaderArtLK_A01 = 10

partHeaderArtLK_A02 = 09

partHeaderArtLK_A03 = 95

partHeaderArtLK_A04 = 38

元素应该看起来像

partHeaderArtLK = 10 09 95 38.

(注意:我插入了虚线分隔符以使事情更清楚。它们不(也不能)存在于实际文件中。)

这是我目前的尝试:

if (line.contains("Name")&& line.contains("_")) {
   String basicName = line;
   cutName = basicName.split("=")[1].trim();//get substring after '='
   cutName = cutName.substring(0,cutName.lastIndexOf("_"));//removes '_'?

   importantName.add(i, (cutName + " = "));//add to element i
   System.out.println("Line reads: " + basicName);
   System.out.println("Part: " + cutName);

   do{                   
    if (line.contains("Value")) {
      Hex = line.split("=")[1].trim();//get substring after '='
      importantNumber.add(i, Hex);//get substring after '='
      System.out.println("Value: " + Hex);                        
    }//end if                  
  }while(!"Value".contains(line = reader.readLine()));
   while (!placeToFinish[i].equals(line = reader.readLine()));

 }else    
   if(line.contains("Name")) {
     String basicName = line;
     cutName = basicName.split("=")[1].trim();//get substring after '='

     importantName.add(i, (cutName + " = "));//get substring after '='
     System.out.println("Line reads: " + basicName);
     System.out.println("Part: " + cutName);
     System.out.println("Number: " + importantNumber.indexOf(i) + "\n"); 

    do{  
      if (line.contains("Value")) {
       Hex = line.split("=")[1].trim();//get substring after '='
       importantNumber.add(i, Hex);//get substring after '='
     }//end if                    
   }while (!"Value".contains(line = reader.readLine()));
    while (!placeToFinish[i].equals(line = reader.readLine()));
 }//end if

这里是完整代码的链接:http://justpaste.it/d3u0
感谢所有算法或代码。

提前致谢!

【问题讨论】:

  • 代码太多了,伙计!!请发布重要部分。
  • 好的,会的。我会为任何需要它的人发布完整代码的链接。
  • @user2798632 您是否考虑过使用简单的状态机?那可能行得通。另一种方法是仅在您确认下一个名称不是前一个名称的延续后才最终确定前一个值。
  • @Eric Stein 我从未使用过状态机,对它们一无所知。我也考虑过你提到的方法,但我仍在努力弄清楚如何做到这一点:/

标签: java arrays algorithm list sorting


【解决方案1】:

你这样做的方式有点复杂(对不起,我什至没有阅读漏洞代码)。

根据您想要的输出,我会这样做:

我会使用Map,它的键名是没有下划线后的部分,值是List

即:

当您阅读以Name 开头的行时,从该行中提取该名称并删除下划线(包括)之后的部分。将该名称保存在变量中,whitch 在循环中保持不变。

当您读取以Value 开头的行时,再次提取该值并使用您之前保存的名称从Map 中查找相应的List。如果List 不存在,则创建一个并将其放入Map。然后将值添加到List

这是它的样子:

private Map<String, List<String>> readValues(BufferedReader reader) throws IOException {
    Map<String, List<String>> nameToValuesMap  = new HashMap<String, List<String>>();
    String line = null;
    String actName = null; 
    while((line = reader.readLine()) != null) {
        if(line.startsWith("Name")) {
            String[] split = line.split("\\s*=\\s*", 2);
            String name = split[1];
            int i = name.indexOf('_');
            if(i != -1) {
                name = name.substring(0, i);
            }
            actName = name;
        } else if(line.startsWith("Value")) {
            String[] split = line.split("\\s*=\\s*", 2);
            String value = split[1].replace("0x", "");
            if(actName != null) {
                List<String> values = nameToValuesMap.get(actName);
                if(values == null) {
                    values = new ArrayList<String>();
                    nameToValuesMap.put(actName, values);
                }
                values.add(value);
            }
        }
    }

    return nameToValuesMap;
}

对于一些测试,我使用了您发布的示例文本:

@Test
public void readpartValues() throws IOException {
    String fielData = "[Device|EEP_FEATUREKOI_HFS_Max|Kostia]\r\n" + 
            "--------------------------------\r\n" + 
            "Name(1) = partHeader_A01\r\n" + 
            "Value(1) = 0x10\r\n" + 
            "Desc(1) = (Address 0x000) Article No. / P.C.B No Byte 1\r\n" + 
            "Name(2) = partHeader_A02\r\n" + 
            "Value(2) = 0x9\r\n" + 
            "Desc(2) = (Address 0x001) Article No. / P.C.B No Byte 2\r\n" + 
            "Name(3) = partHeader_A03\r\n" + 
            "Value(3) = 0x95\r\n" + 
            "Desc(3) = (Address 0x002) Article No. / P.C.B No Byte 3\r\n" + 
            "Name(4) = partHeader_A04\r\n" + 
            "Value(4) = 0x38\r\n" + 
            "Desc(4) = (Address 0x003) Article No. / P.C.B No Byte 4\r\n" + 
            "----------------------------------\r\n" + 
            "Name(12) = AdrIctPcbTestDate_Day\r\n" + 
            "Value(12) = 0xFF\r\n" + 
            "Desc(12) = (Address 0x00B) Test Date : Day\r\n" + 
            "---------------------------------\r\n" + 
            "Name(13) = AdrIctPcbTestDate_Month\r\n" + 
            "Value(13) = 0xFF\r\n" + 
            "Desc(13) = (Address 0x00C) Test Date : Month\r\n" + 
            "---------------------------------\r\n" + 
            "Name(14) = AdrIctPcbTestTime_Hour\r\n" + 
            "Value(14) = 0xFF\r\n" + 
            "Desc(14) = (Address 0x00D) Test Time : Hour\r\n" + 
            "---------------------------------\r\n" + 
            "Name(15) = AdrIctPcbTesTime_Minute\r\n" + 
            "Value(15) = 0xFF\r\n" + 
            "Desc(15) = (Address 0x00E) Test Time : Minute";


    BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(fielData.getBytes())));

    Map<String, List<String>> nameToValuesMap  = readValues(reader);
    reader.close();

    List<String> partHeaderValues = nameToValuesMap.get("partHeader");
    System.out.println("partHeader = " + partHeaderValues.toString());

    List<String> adrIctPcbTestTimeValues = nameToValuesMap.get("AdrIctPcbTestTime");
    System.out.println("AdrIctPcbTestTime = " + adrIctPcbTestTimeValues.toString());
}

输出

partHeader = [10, 9, 95, 38]
AdrIctPcbTestTime = [FF]

希望这会有所帮助!

【讨论】:

  • @EricStein,我不认为这看起来像是家庭作业,而且答案不值得投票,无论谁这样做,他至少应该留下建设性的评论。
  • 完全同意。我投了赞成票只是为了平衡不应有的反对票。
  • @Eric Stein 这是不是 家庭作业。我的老板让我做一些编码的任务(我知道一点Java),我遇到了这个问题。
  • @A4L 我想我可以改变这个。有什么办法可以去掉括号吗?我会赞成答案,但没有足够的 Rep(15)。
  • @user2798632 最严格的仅来自List#toString(),列表中的元素都可以,只需遍历列表并获取值! -> for(String valueWithoutBrackets : list) { ... }
【解决方案2】:

基本思想 - 创建输出映射,如“名称 ->(值列表)”。此后 - 打印它。 但我不确定,Java 是否适合解决此任务。在 PERL 上查看我的程序,它可以完成这项工作:

#!/usr/local/bin/perl -w

my %nv;
while(<>) {
  my ($nm, $ndx, $val) = m/^(\w+)?\((\d+)\)\s*=\s*(\w+)/;
  next unless $val;
  $nv{$ndx}{$nm} = $val;
}

my %out;
foreach my $k(sort keys %nv) {
  my $name = $nv{$k}{"Name"};
  $name =~ s/_.+//;
  push(@{$out{$name}}, map {s/^0x//; $_ } $nv{$k}{"Value"});
}

while(my ($nm, $vlist) = each %out) {
  print "$nm = " . join(" ", @{$vlist}) . "\n";
}

样本的输出:

$ ./nv.pl nv.txt
AdrIctPcbTesTime = FF
AdrIctPcbTestDate = FF FF
partHeader = 10 9 95 38
AdrIctPcbTestTime = FF

【讨论】:

  • 感谢您的回答。输出几乎正确,但我不知道 PERL,这只是已经用 Java 编写的更大程序的一部分。
  • 我编辑了程序,这个版本删除了每个值开头的“0x”,如果存在的话。此外,它通过索引而不是行号链接对“Name=Value”..
  • 哈哈再次感谢。无论如何,对于那些了解 PERL 的人来说,它都会派上用场。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 2019-03-09
  • 1970-01-01
  • 2012-10-01
相关资源
最近更新 更多