Domanda

Ho un file di testo che appare come:

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

cioè., Un'etichetta di testo in chiaro seguita da alcune righe con 1/0 separati da spazi. Il numero di righe di 1/0 è variabile, ma ogni riga tra due etichette particolari deve avere lo stesso numero di 1 / 0s (sebbene potrebbe potenzialmente meno).

Come faccio afferro ogni nome di file + pezzo con uno scanner? C'è un modo elegante per far rispettare la consistenza del numero di righe (e di fornire una sorta di feedback se non sono coerenti)?

mi viene da pensare che ci potrebbe essere un modo conveniente con la specifica delimitatore di intelligente, ma io non riesco a ottenere che il lavoro.

È stato utile?

Soluzione 2

Ancora meglio, dopo una risposta utile ad un'altra domanda (grazie 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;
}

Altri suggerimenti

lo farei il modo più semplice. Afferrare ogni riga come un String, e alimentarlo attraverso, dire, un'espressione regolare che corrisponde al modello 1-o-0-seguita-da-spazio. Se corrisponde, trattarla come una fila. In caso contrario, trattarla come un'etichetta di testo in chiaro. Controllare la consistenza riga-colonna-formato dopo il fatto controllando tale matrice di ogni etichetta di dati corrisponde alla dimensione della matrice della prima etichetta di dati.

EDIT: Non ero a conoscenza della classe Scanner, anche se suona a portata di mano. Credo che l'idea essenziale dovrebbe essere ancora meno lo stesso ... utilizzare il Scanner per analizzare l'input, e gestire la questione delle dimensioni te.

Inoltre, in teoria, si potrebbe produrre un'espressione regolare che sarebbe partita l'etichetta e l'intero array, anche se non so se si può produrre uno che garantisca che corrisponda solo insiemi di linee con lo stesso numero di valori in ciascuna riga. Ma poi, di istituire controlli più automatizzato, si sarebbe probabilmente necessario costruire una seconda espressione regolare che corrisponde esattamente la dimensione della matrice della prima voce, e utilizzarlo per tutti gli altri. Penso che questo sia un caso in cui la cura è peggiore della malattia.

Si avrebbe bisogno di aprire il file e ciclo attraverso ogni linea con readLine () fino a quando si colpisce la fine del file.

- ho pensato che si sta facendo la consistenza mentre attraversate il file. Se si desidera memorizzare le informazioni e utilizzare in un secondo momento, vorrei considerare l'utilizzo di un certo tipo di struttura dati.

Mentre si attraversano questo, è possibile controllare la riga con un semplice regex per verificare se si tratta di un nome di etichetta. In caso contrario, dividere la riga sulla base del '' (spazio) e tornerà a voi in un array. Poi controllare la dimensione in base a una dimensione costante.

pseudocodice di base:

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");
    }
}

Si potrebbe anche aggiungere un altro ciclo se non si conosce la dimensione che ci si aspetta per ogni riga e mettere un po 'di logica per trovare la dimensione più comune e quindi capire cosa non corrisponde. Non sono sicuro di quanto sia complicato il vostro controllo di coerenza ha bisogno di essere.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top