1

次のようなテキストファイルがあります。

name1
1 0 1 0 1
0 1 1 1 0
0 0 0 0 0
name2
1 0 1 0 1
0 0 1 1 0
0 0 0 0 1

つまり、平文のラベルの後にスペースで区切られた 1/0 の数行が続きます。1/0 の行数は可変ですが、任意の 2 つの特定のラベル間の各行には、同じ数の 1/0 が含まれている必要があります (そうでない可能性もあります)。

各名前と行のチャンクをスキャナーで取得するにはどうすればよいですか? 行数の一貫性を強制するエレガントな方法はありますか (一貫していない場合は何らかのフィードバックを提供します)。

巧妙な区切り文字指定で便利な方法があるのではないかと考えていますが、うまくいかないようです。

4

3 に答える 3

1

さらに良いことに、別の質問に対する役立つ回答の後 ( Bartに感謝):

static final String labelRegex="^\\s*\\w+$";
static final Pattern labelPattern = Pattern.compile(labelRegex, Pattern.MULTILINE);
Matcher labelMatcher = labelPattern.matcher("");

static final String stateRegex = "([10] )+[10]\\s+";
static final String statesRegex = "("+stateRegex+")+";
static final Pattern statesPattern = Pattern.compile(statesRegex, Pattern.MULTILINE);
Matcher stateMatcher = statesPattern.matcher("");

static final String chunkRegex = "(?="+labelRegex+")";
static final Pattern chunkPattern = Pattern.compile(chunkRegex,Pattern.MULTILINE);
Scanner chunkScan;

public void setSource(File source) {
    if(source!=null && source.canRead()) {
     try {
      chunkScan = new Scanner(new BufferedReader(new FileReader(source)));
      chunkScan.useDelimiter(chunkPattern);
     } catch (IOException e) {
      e.printStackTrace();
     }
    }
}

public Map<String, List<GraphState>> next(int n) {
 Map<String,List<GraphState>> result = new LinkedHashMap<String,List<GraphState>>(n);
  String chunk, rows;
  int i=0;
  while (chunkScan.hasNext()&&i++<n) {
    chunk = chunkScan.next().trim();
    labelMatcher.reset(chunk);
    stateMatcher.reset(chunk);
   if (labelMatcher.find()&&stateMatcher.find()) {
    rows = stateMatcher.group().replace(" ", "");
    result.put(labelMatcher.group(), rowsToList(rows.split("\\n")));
   }
  }
  return result;
}
于 2009-10-10T16:24:52.023 に答える
1

私はそれを簡単な方法で行います。各行を として取得Stringし、たとえば、1-or-0-followed-by-space パターンに一致する正規表現を介してフィードします。一致する場合は、行として扱います。そうでない場合は、プレーンテキスト ラベルのように扱います。すべてのラベルのデータ配列が最初のラベルのデータ配列のサイズと一致することを確認することにより、事後に行と列のサイズの一貫性を確認します。

編集:Scanner便利そうに見えますが、クラスを知りませんでした。本質的な考え方はほぼ同じであると思います... を使用しScannerて入力を解析し、サイズの問題を自分で処理します。

また、理論的には、ラベルと配列全体に一致する正規表現を作成できますが、それぞれに同じ数の値を持つ行のセットのみに一致することを保証する正規表現を作成できるかどうかはわかりません行。ただし、さらに自動化されたチェックを設定するには、おそらく最初のエントリの配列サイズと正確に一致する 2 番目の正規表現を作成し、それを他のすべてのエントリに使用する必要があります。これは、治療が病気よりも悪い場合だと思います。

于 2009-10-09T17:14:00.903 に答える
0

ファイルを開き、ファイルの最後に到達するまで readLine() を使用してすべての行をループする必要があります。

-- ファイルをトラバースするときに一貫性を保っていると思います。情報を保存して後で使用する場合は、何らかのデータ構造を使用することを検討します。

これをたどると、単純な正規表現で行をチェックして、それがラベル名であるかどうかを確認できます。そうでない場合は、' ' (スペース文字) に基づいて行を分割すると、配列で返されます。次に、一貫したサイズに基づいてサイズを確認します。

基本的な擬似コード:

int consistentSize = 5; // assume you have a size in mind

while ( (line = readLine()) != EOF)
{
    // check for if label, if it's a simple name, you won't really need a regex
    if (line == label)
    {
         // not sure if you want to do any consistency checking in here
    } else {
         String[] currLine = line.split(' ');
         bool consist = true;
         // now loop through currLine and do a check if each character is a number
         for (int i = 0; i < currLine.size(); i++)
         {
            // can't remember java function for this (isNum() I think)
            if (!currLine[i].isNum) { consist = false; break; }
         }
         // if got past this, the row has all numbers, therefore it is ok
            // could easily add another array to keep track of rows that didn't have valid numbers and suhc
         if (currLine.size() < consistentSize) System.out.println("row "+j + " is inconsistent");
    }
}

各行に予想されるサイズがわからない場合は、別のループを追加し、最も一般的なサイズを見つけて、一致しないものを特定するロジックを追加することもできます。一貫性チェックがどれほど複雑である必要があるかはわかりません。

于 2009-10-09T17:18:54.417 に答える