Разделить строку на столбцы на основе расстояния между значениями

Я работаю с неструктурированными текстовыми данными, экспортированными из PDF. Исходные данные взяты из таблицы в формате PDF, которая была преобразована в текстовый формат, поэтому остается только общая структура. Отдельный раздел, на который я смотрю, раньше был таблицей.

Так, например, вот пример ввода

  A        B     C     D         E
 1        2                     3
 4              6     7    

Первая строка указывает заголовки, а следующие строки - значения.

К счастью, интервал сохраняется (в некоторой степени): между каждым столбцом всегда будет как минимум два пробела. Однако фактическое количество пробелов будет варьироваться в зависимости от того, как синтаксический анализатор решил обработать его в зависимости от структуры таблицы.

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

{"A", "B", "C", "D", "E"}
{"1", "2",  "",  "", "3"}
{"4",  "", "6", "7",  ""}

Можно ли это точно сделать, учитывая только эту информацию?

1 ответ

Решение

Я думаю, что вы можете получить индекс заголовка (A, B, ...) в строке и сравнить его с индексом значения в каждой строке, чтобы получить наиболее близкий... Я попытался быстро и получил этот результат:

public static void main(String[] args) {
    String headerColumn = "  A        B     C     D         E";
    String firstLine = " 1        2                     3";
    String secondLine = " 4              6     7    ";

    Map<Integer, String> indexHeaderMap = new HashMap<Integer, String>();
    // Get header indexes
    for (int i = 0; i < headerColumn.length(); i++) {
        String currChar = String.valueOf(headerColumn.charAt(i));
        if (!currChar.equals(" ")) {
            indexHeaderMap.put(i, currChar);
        }
    }

    // Parse first line
    parseLine(firstLine, indexHeaderMap);
    // Parse second line
    parseLine(secondLine, indexHeaderMap);
}

И функции:

private static void parseLine(String pLine, Map<Integer, String> pHeaderMap) {
    for (int i = 0; i < pLine.length(); i++) {
        String currChar = String.valueOf(pLine.charAt(i));
        if (!currChar.equals(" ")) {
            int valueColumnIndex = getNearestColumnIndex(i, pHeaderMap);
            System.out.println("Value " + currChar + " is on column " + pHeaderMap.get(valueColumnIndex));
        }
    }
}

private static int getNearestColumnIndex(int pIndex,
        Map<Integer, String> pHeaderMap) {
    int minDiff = 500;
    int nearestColumnIndex = -1;
    for(Map.Entry<Integer, String> mapEntry : pHeaderMap.entrySet()) {
        int diff = Math.abs(mapEntry.getKey() - pIndex);
        if (diff < minDiff) {
            minDiff = diff;
            nearestColumnIndex = mapEntry.getKey();
        }
    }

    return nearestColumnIndex;
}

Вот вывод:

Value 1 is on column A
Value 2 is on column B
Value 3 is on column E
Value 4 is on column A
Value 6 is on column C
Value 7 is on column D

Я надеюсь, что это достаточно полезно, чтобы получить ожидаемый результат!

Другие вопросы по тегам