Pregunta

Tengo un archivo de texto que se parece a:

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

es decir., Una etiqueta de texto claro seguido por unas pocas filas con 1/0 separadas por espacios. El número de filas de 1/0 es variable, pero cada fila entre dos etiquetas particulares debe tener el mismo número de 1 / 0s (aunque podría potencialmente no).

¿Cómo se agarra cada nombre + filas trozo con un escáner? ¿Hay alguna manera elegante de hacer cumplir la consistencia del número de filas (y proporcionar algún tipo de retroalimentación si no son consistentes)?

Estoy pensando que podría ser una manera conveniente con la especificación delimitador inteligente, pero me parece que no puede conseguir ese trabajo.

¿Fue útil?

Solución 2

Aún mejor, después de un útiles a otra pregunta (gracias 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;
}

Otros consejos

Yo lo haría de la forma más sencilla. Coge cada línea como un String, y se alimentan a través de, por ejemplo, una expresión regular que coincide con el patrón 1-o-0 seguido por el espacio. Si coincide, tratarla como si fuera una fila. Si no es así, tratarla como una etiqueta de texto plano. Compruebe que la consistencia fila-columna de tamaño después del hecho por el control de esa matriz de cada etiqueta de datos coincide con el tamaño de la matriz de la primera etiqueta de datos.

EDIT: yo no era consciente de la clase Scanner, aunque suene muy bien. Creo que la idea esencial aún debe ser más o menos lo mismo ... utilizar el Scanner para analizar su entrada y manejar la cuestión de los tamaños usted mismo.

Además, en teoría, se podría producir una expresión regular que se correspondería con la etiqueta y todo el conjunto, aunque no sé si se puede producir uno que garantice que sólo coincide con conjuntos de líneas con el mismo número de valores en cada fila. Pero entonces, para establecer una comprobación más automatizada, es probable que se necesitaría para construir una segunda expresión regular que coincide exactamente con el tamaño de la matriz de la primera entrada, y utilizarla para todos los demás. Creo que este es un caso en que el remedio es peor que la enfermedad.

Usted tendría que abrir el archivo y bucle a través de cada línea con readLine () hasta llegar a la final del archivo.

- Supuse que está haciendo consistencia a medida que atraviesan el archivo. Si desea almacenar la información y utilizarla más tarde, me gustaría considerar el uso de algún tipo de estructura de datos.

A medida que se recorre esto, se puede comprobar la fila con una simple expresión regular para comprobar si se trata de un nombre de etiqueta. Si no es así, dividir la fila basado en el '' (carácter de espacio) y volverá a usted en una matriz. A continuación, comprobar el tamaño basado en un tamaño consistente.

pseudocódigo básica:

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

También puede añadir otro bucle si no sabe el tamaño que espera para cada fila y poner un poco de lógica en la que encontrar el tamaño más común y luego averiguar lo que no coincide. No estoy seguro de lo complicado de su cuenta de cheques de consistencia tiene que ser.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top