Вопрос

У меня есть текстовый файл, который выглядит как:

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, является переменным, но каждая строка между любыми двумя конкретными метками должна иметь одинаковое количество 1/0 (хотя потенциально может и не иметь).

Как мне захватить каждый фрагмент name + rows с помощью сканера?Есть ли какой-нибудь элегантный способ обеспечить согласованность количества строк (и предоставить какую-то обратную связь, если они не согласованы)?

Я думаю, что мог бы быть удобный способ с умной спецификацией разделителя, но, похоже, я не могу заставить это работать.

Это было полезно?

Решение 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 чтобы проанализировать ваши входные данные и самостоятельно решить вопрос о размерах.

Кроме того, теоретически, вы могли бы создать регулярное выражение, которое соответствовало бы метке и всему массиву, хотя я не знаю, можете ли вы создать такое, которое гарантировало бы, что оно соответствует только наборам строк с одинаковым количеством значений в каждой строке.Но затем, чтобы настроить более автоматическую проверку, вам, вероятно, потребуется создать второе регулярное выражение, которое точно соответствует размеру массива первой записи, и использовать его для всех остальных.Я думаю, что это тот случай, когда лекарство хуже, чем болезнь.

Вам нужно будет открыть файл и перебирать каждую строку с помощью 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");
    }
}

Вы также могли бы добавить еще один цикл, если вы не знаете ожидаемый размер для каждой строки, и ввести некоторую логику, чтобы найти наиболее распространенный размер, а затем выяснить, что не соответствует.Я не уверен в том, насколько сложной должна быть ваша проверка согласованности.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top