2010-04-22 64 views
0

我知道像1 3 7 8这样的匹配的charwise位置。我需要知道他们的相应行号。Java:根据“ n”的数字计算charwise位置的数字。

实施例:file.txt的

匹配:X

欢,:1 3 7 8

旺旺:1 2 4 4

$ cat file.txt 
X2 
X 
4 
56XX 

[新增:没有注意到许多面向行的比赛,有可能是更容易的方法与栈做]

$ java testt  
1 
2 
4 
$ cat testt.java 
import java.io.*; 
import java.util.*; 
public class testt { 

    public static String data ="X2\nX\n4\n56XX"; 
    public static String[] ar = data.split("\n"); 

    public static void main(String[] args){ 
     HashSet<Integer> hs = new HashSet<Integer>(); 
     Integer numb = 1; 
     for(String s : ar){ 
      if(s.contains("X")){ 
       hs.add(numb); 
       numb++; 
      }else{ 
       numb++; 
      } 
     } 
     for (Integer i : hs){ 
      System.out.println(i); 
     } 
    } 
} 

回答

1

首先,你的例子是无效的 - 你的样品中的字符X在位置(0,3,9,10),不(1,3,7,8)发现。你要将换行符从你的推算中排除,并且你应该从索引1开始计数,当你从零开始时。

将绝对位置与行号关联的唯一方法是映射换行符的位置以进行比较。正如其他人所说的那样,在飞行中这样做并不困难 - 只是缓慢而乏味。如果您要进行多次查找,并且您知道数据在两次之间不会更改,则应该创建一个静态地图。你可以使用一个列表或一个地图,但有一个名为SizeSequence的类是理想的目的。检查了这一点:

import javax.swing.SizeSequence; 

public class Test 
{ 
    static SizeSequence createLineMap(String s) 
    { 
    String[] lines = s.split("(?<=\n)"); 
    SizeSequence sseq = new SizeSequence(lines.length); 
    for (int i = 0; i < lines.length; i++) 
    { 
     sseq.setSize(i, lines[i].length()); 
    } 
    return sseq; 
    } 

    public static void main(String[] args) throws Exception 
    { 
    String input = "X2\nX\n4\n56XX"; 
    SizeSequence lineMap = createLineMap(input); 
    String target = "X"; 
    int pos = -1; 
    while ((pos = input.indexOf("X", pos+1)) != -1) 
    { 
     System.out.printf("'%s' found in line %d (index %d)%n", 
      target, lineMap.getIndex(pos) + 1, pos); 
    } 
    } 
} 

输出:

 
'X' found in line 1 (index 0) 
'X' found in line 2 (index 3) 
'X' found in line 4 (index 9) 
'X' found in line 4 (index 10)

注意我是如何分割的lookbehind(?<=\n),而不是仅仅\n。这样我确保每行的字符数包括换行;所有字符都必须计算在内。 (在那张纸上,我知道有不同的行分隔符和代理对存在问题,但为了清楚起见,我将它们排除在外)。

您可以使用Scanner的findWithinHorizon()方法对文件使用相同的技术split()和'indexOf()`。

0

增量的计数器每一次你读一行,而不是每次读一个字符。如果您一次读取一个字符,则每当看到一个EOL字符时都会增加。

0
  1. 嗯......通过逐行阅读文件,直到你得到一个匹配并增加你看过的每一行的计数器为止?
1
public static String data ="X2\naaaaXXaaaa\naaaa\naaaaaaX\naaaaaaXaX"; 
public static String[] lines = data.split("\n"); 

public static void main(String[] args){ 
     Map<Integer, List<Integer>> result = new HashMap<Integer, List<Integer>>(); 

     Integer lineNum = 1; 


     for(String s : lines){ 

      boolean keepSearching = true; 
      List<Integer> charPositions=null; 
      Integer charNum=0, lastCharNum=0; 

      while(keepSearching){ 

       if (start == true){ 
        charNum = s.indexOf("X", lastCharNum); 
        start = false; 
       }else{ 
        charNum = s.indexOf("X", lastCharNum+1); 
       } 

       if(charNum >= 0){ 
        if(charPositions== null){ 
         charPositions = new ArrayList<Integer>(); 
        } 
        charPositions.add(charNum); 
        lastCharNum = charNum; 
       }else{ 
        keepSearching = false; 
        if(charPositions!= null){ 
         result.put(lineNum, charPositions); 
        } 
       } 
      } 

      lineNum++; 

     } 
     for (Integer i : result.keySet()){ 
      System.out.print("Line "+i+" : "); 
      for(Integer j : result.get(i)){ 
       System.out.print("at char "+j+", "); //you should start for the end if you want to print in the right order ! 
      } 
      System.out.println(); 
     } 
    } 

Output : 
Line 1 : at char 0, 
Line 2 : at char 4, at char 5, 
Line 4 : at char 6, 
Line 5 : at char 6, at char 8, 
+0

what aaut“Line 1:at char 0”? – hhh 2010-04-22 15:15:26

+0

用“boolean start”和循环固定:boolean keepSearching = true; boolean start = true; 列表 charPositions = null; 整数charNum = 0,lastCharNum = 0; (keepSearching){ charNum = s.indexOf(“X”,lastCharNum + 1);如果(start == true && lastCharNum == 0){ charNum = s.indexOf(“X”,lastCharNum); start = false; } – hhh 2010-04-22 16:46:50

+0

你是对的,谢谢。我修正了代码:) – 2010-04-23 07:46:51