Java スキャナーの頭痛
-
20-09-2019 - |
質問
次のようなテキスト ファイルがあります。
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 が含まれている必要があります (ただし、そうでない可能性もあります)。
スキャナーで各名前と行のチャンクを取得するにはどうすればよいですか?行数の一貫性を強制する (一貫性がない場合は何らかのフィードバックを提供する) エレガントな方法はありますか?
区切り文字をうまく指定して便利な方法があるのではないかと考えていますが、それがうまくいかないようです。
解決 2
さらに良いのは、 別の質問に対する役立つ回答 (ありがとう バート):
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;
}
他のヒント
私はそれを簡単な方法を行うだろう。 String
として各ラインを取得し、それを介して送り、1または0が、その後・バイ・スペースパターンと一致する正規表現を言います。それが一致した場合、行のように扱います。ない場合は、プレーンテキストのラベルのように扱います。データのすべてのラベルの配列は、データの最初のラベルの配列のサイズと一致していることをチェックすることにより、事実の後に行と列サイズの一貫性をチェックします。
編集:それは便利に聞こえるが、私は、Scanner
クラスを認識していませんでした。私は基本的なアイデアは、まだほぼ同じであるべきだと思う...あなたの入力を解析し、サイズを自分の問題を処理するためにScanner
を使用します。
また、理論的には、あなたは、ラベルや配列全体にマッチする正規表現を作り出すことができます各行内の値。しかし、その後、より自動化されたチェックを設定するために、あなたはおそらく正確に最初のエントリの配列サイズが一致する2番目の正規表現を構築し、他のすべてのためにそれを使用する必要があるだろう。私は、これは治療法は病気よりも悪化している場合だと思います。
あなたは、ファイルの終わりを打つまでの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");
}
}
あなたは、あなたが行ごとに期待サイズがわからない場合は、別のループを追加して、最も一般的なサイズを検索し、一致していないかを把握するには、いくつかのロジックを置くことができます。私はあなたの整合性チェックをする必要がありますどのように複雑なのか不明だ。