Pergunta

Eu tenho um arquivo de texto que se parece:

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

ou seja, um rótulo de texto simples, seguido de algumas linhas com 1/0 separadas por espaços. O número de linhas de 1/0 é variável, mas cada linha entre dois rótulos específicos deve ter o mesmo número de 1/0s (embora possa potencialmente não).

Como pego cada nome+linhas com um scanner? Existe alguma maneira elegante de fazer cumprir a consistência no número de linhas (e fornecer algum tipo de feedback se não forem consistentes)?

Estou pensando que pode haver uma maneira conveniente com especificações inteligentes de delimitador, mas não consigo fazer isso funcionar.

Foi útil?

Solução 2

Melhor ainda depois de um resposta útil para outra pergunta (obrigado 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;
}

Outras dicas

Eu faria isso da maneira simples. Pegue cada linha como um String, e alimente-o, digamos, uma expressão regular que corresponde ao padrão de 1 ou 0-seguido por espaço. Se corresponder, trate -o como uma linha. Caso contrário, trate -o como um rótulo de texto simples. Verifique a consistência do tamanho da coluna de linha após o fato verificando se a matriz de dados de cada rótulo corresponde ao tamanho da matriz de dados da primeira etiqueta.

Editar: eu não estava ciente do Scanner classe, embora pareça útil. Eu acho que a idéia essencial ainda deve ser aproximadamente a mesma ... use o Scanner Para analisar sua contribuição e lidar com a questão dos tamanhos.

Além disso, em teoria, você pode produzir uma expressão regular que corresponderia ao rótulo e a toda fileira. Mas então, para configurar uma verificação mais automatizada, você provavelmente precisará construir uma segunda expressão regular que corresponda exatamente ao tamanho da matriz da primeira entrada e usá -la para todos os outros. Eu acho que este é um caso em que a cura é pior que a doença.

Você precisaria abrir o arquivo e percorrer todas as linhas com readline () até chegar ao final do arquivo.

- Presumi que você está fazendo consistência ao atravessar o arquivo. Se você deseja armazenar as informações e usá -las mais tarde, eu consideraria usar algum tipo de estrutura de dados.

Ao atravessar isso, você pode verificar a linha com um regex simples para verificar se é um nome de etiqueta. Caso contrário, divida a linha com base no '' (caractere espacial) e ela retornará a você em uma matriz. Em seguida, verifique o tamanho com base em um tamanho consistente.

Pseudocódigo básico:

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

Você também pode adicionar outro loop se não souber o tamanho que espera de cada linha e colocar alguma lógica para encontrar o tamanho mais comum e depois descobrir o que não corresponde. Não tenho certeza de quão complicada sua verificação de consistência precisa ser.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top