Как удалить почти дубликаты целых чисел из списка?

Я разбираю некоторые PDF-файлы в Python. Эти PDF-файлы визуально организованы в строки и столбцы. Сценарий pdftohtml преобразует эти PDF-файлы в формат XML, полный <text> тегов <text> которые не имеют никакой иерархии. Затем мой код должен сортировать эти теги <text> обратно в строки.

Поскольку каждый <text> имеет атрибуты, такие как «верхние» или «левые» координаты, я написал код для добавления <text> элементов с той же «верхней» координатой в список. Этот список фактически один ряд.

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

 for side in page: tops = list( set( [ d['top'] for d in side ] ) ) tops.sort() for top in tops: row = [] for blob in side: if int(blob['top']) == int(top): row.append(blob) rows.append(row) 

Этот код отлично подходит для большинства файлов PDF, которые я обрабатываю. Но бывают случаи, когда элементы, находящиеся в одной строке, имеют несколько разные верхние значения, от одного до двух.

Я пытаюсь адаптировать свой код, чтобы стать немного пушистым.

Сравнение на дне кажется достаточно простым для исправления. Что-то вроде этого:

  for blob in side: rangeLower = int(top) - 2 rangeUpper = int(top) + 2 thisTop = int(blob['top']) if rangeLower <= thisTop <= rangeUpper : row.append(blob) 

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

  tops = list( set( [ d['top'] for d in side ] ) ) 

В этих крайних случаях я получаю список вроде:

 [925, 946, 966, 995, 996, 1015, 1035] 

Как я мог адаптировать этот код, чтобы избежать «995» и «996» в списке? Я хочу, чтобы в итоге я получил только одно значение, когда целые числа находятся в пределах 1 или 2 друг от друга.

2 Solutions collect form web for “Как удалить почти дубликаты целых чисел из списка?”

  • Сортируйте список, чтобы поместить близкие значения рядом друг с другом
  • Используйте reduce для фильтрации значения в зависимости от предыдущего значения

Код:

 >>> tops = [925, 946, 966, 995, 996, 1015, 1035] >>> threshold = 2 >>> reduce(lambda x, y: x + [y] if len(x) == 0 or y > x[-1] + threshold else x, sorted(tops), []) [925, 946, 966, 995, 1015, 1035] 

С несколькими смежными значениями:

 >>> tops = range(10) >>> reduce(lambda x, y: x + [y] if len(x) == 0 or y > x[-1] + threshold else x, sorted(tops), []) [0, 3, 6, 9] 

редактировать

Сокращение может быть немного громоздким для чтения, так что вот более простой подход:

 res = [] for item in sorted(tops): if len(res) == 0 or item > res[-1] + threshold: res.append(item) 

Ответ @ njzk2 тоже работает, но эта функция фактически показывает, что происходит, и ее легче понять:

 >>> def sort(list): ... list.sort() #sorts in ascending order ... x = range(0, len(list), 1) #gets range ... x.reverse() #reverses ... for k in x: ... if list[k]-1 == list[k-1]: #if the list value -1 is equal to the next, ... del(list[k-1]) #remove it ... return list #return ... >>> tops = [925, 946, 966, 995, 996, 1015, 1035] >>> sort(tops) [925, 946, 966, 996, 1015, 1035] >>> 
  • Сгенерировать все возможные комбинации из списка int под лимитом
  • Список Python не отражает переменные изменения
  • Что означает locals () '] в Python?
  • Функция Python: переменная и строка
  • Показать все возможные группировки списка, учитывая только количество подписок (длины являются переменными)
  • Список сортировки в Python двумя другими списками
  • Сгладить (нерегулярный) список списков
  • Передавать элементы списка в качестве аргументов функции в python
  • Можно ли преобразовать тип списка в генератор без повторения?
  • Преобразование чисел в классы в списке python
  • Как создать двух циклов для представления в python
  • Python - лучший язык программирования в мире.