Пример дублированной и объединенной строки:
16.01068.0%0 8p%.a .p .a.
Желаемая подстрока для извлечения:
16.008% p.a.
Более полный пример:
CCoonnttiinnggeenntt CCoouuppoonn 16.01068.0%0 8p%.a .p (.Ma.o (nMtholyn)thly)
Желаемая подстрока:
Contingent Coupon 16.008% p.a. (Monthly)
Моя проблема в том, что когда исходная подстрока уже содержит повторяющиеся символы (например, два 0
в 16.008
), моя текущая функция иногда сохраняет неправильный повторяющийся символ (давая неправильный результат 16.080
).
Вы можете думать об этом явлении как о дублирующейся строке, отстающей от основной строки на некоторое количество символов. Поскольку дублирующая строка с индексом i всегда должна соответствовать основной строке с индексом i, вы можете использовать эту характеристику как способ определить, принадлежит ли входящий символ дублирующей строке или основной строке. Чтобы обрабатывать случаи, когда правильная строка содержит два одинаковых последовательных символа и встречается второй из них, вы можете использовать алгоритм поиска с возвратом, чтобы найти путь, ведущий к соответствующей повторяющейся строке.
Обратите внимание, что дублирующиеся символы, скорее всего, являются результатом эмуляции жирного шрифта, но поскольку в дублирующихся пробелах ничего не видно, они, к сожалению, идентифицируются сканером PDF как один пробел. В качестве обходного пути вы можете искусственно заменить каждый пробел во входных данных двумя пробелами, а затем заменить любые два последовательных пробела одним пробелом для вывода. Также обратите внимание, что в вашей входной строке может отсутствовать конечный пробел, поскольку сканер не может идентифицировать его без видимой границы. Вы можете искусственно добавить конечный пробел к входным данным и впоследствии удалить конечные пробелы:
def dedupe(string):
def _dedupe(pos, dupe):
if pos == size:
return dupe == half
char = string[pos]
if (dupe < len(output) and output[dupe] == char and
_dedupe(pos + 1, dupe + 1)):
return True
output.append(char)
if _dedupe(pos + 1, dupe):
return True
output.pop()
string = (string + ' ').replace(' ', ' ')
size = len(string)
half = size // 2
output = []
if _dedupe(0, 0):
return ''.join(output).replace(' ', ' ').rstrip()
raise ValueError('No matching duplicate found.')
так что:
print(dedupe(
"CCoonnttiinnggeenntt CCoouuppoonn 16.01068.0%0 8p%.a .p (.Ma.o (nMtholyn)thly)"
))
выходы:
Contingent Coupon 16.008% p.a. (Monthly)
Демо здесь
Спасибо. Кстати, пробелов нет, строка, возвращаемая пакетом pdfplumber, точно такая, как я ее ввел. Но макет исходной записи таблицы PDF, отсканированной pdfplumber, запутал алгоритм. В моем описании проблемы ошибочно предполагалось, что путаница носит более детерминированный характер, чем она есть на самом деле.
Я понимаю. Дублирующиеся символы, скорее всего, являются результатом эмуляции жирного шрифта, но поскольку в дублирующихся пробелах ничего не видно, они, к сожалению, идентифицируются сканером как один пробел.
Да, я так считаю.
Ну, тогда я обновил свой ответ, указав обходной путь.
Я считаю, что решение должно быть более сложным, чем ваша функция. Вот пример: «11,7151%.7 5%» (что при дедупликации должно быть «11,75%». Без какого-либо предпросмотра невозможно различить следующие два случая: А) первый символ «1» является частью основная строка, второй символ «1» является дубликатом, B) первый и второй символы «1» являются частью основной строки. Кажется, что эти два случая можно различить только тогда, когда мы достигнем третьей «1» и обнаружим, что соответствующий повторяющийся символ имеет индекс меньше, чем предыдущие соответствующие повторяющиеся символы.
Затем я обновил ответ с помощью алгоритма возврата.
Еще раз спасибо! Я сам писал алгоритм возврата. Ты намного быстрее, чем я.
Зачем вы добавляете лишний пробел в конце строки?
Пожалуйста. Как отмечено в обновленном ответе, в вашем вводе, по-видимому, отсутствует конечный пробел, предположительно потому, что сканер не может идентифицировать его без видимой границы, поэтому в качестве обходного пути мы можем добавить конечный пробел к вводу и впоследствии удалить конечные пробелы.
что вам нужно, так это научиться правильно извлекать данные из pdf. вы просто тратите свое время, пытаясь решить эту проблему