如何从列表中去除几乎重复的整数?

0 投票
2 回答
741 浏览
提问于 2025-04-18 03:10

我正在用Python解析一些PDF文件。这些PDF文件的内容在视觉上是按行和列组织的。pdftohtml这个脚本可以把这些PDF转换成一种XML格式,里面有很多松散的<text>标签,但这些标签之间没有任何层级关系。接下来,我的代码需要把这些<text>标签重新整理成行。

每个<text>标签都有一些属性,比如“top”(顶部)或“left”(左侧)坐标,所以我写了代码,把具有相同“top”坐标的<text>项添加到一个列表中。这个列表实际上就是一行。

我的代码首先遍历页面,找到所有独特的“top”值,并把它们添加到一个叫做tops的列表中。然后,它会遍历这个tops列表。对于每个独特的top值,它会查找所有具有该“top”值的项,并把它们添加到一行的列表中。

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中运行得很好。但是,有些情况下,同一行的项目可能有稍微不同的top值,差一两个。

我正在尝试调整我的代码,让它变得更灵活一些。

底部的比较看起来很容易修复。可以这样做:

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

但是我最开始创建的独特top值列表就成了一个问题。我用的代码是

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

在这些特殊情况下,我最终得到的列表像这样:

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

我该如何调整这段代码,以避免列表中出现“995”和“996”?我想确保当整数之间相差1或2时,最终只保留一个值。

2 个回答

0

@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]
>>> 
4
  • 把列表排序,让相近的数值放在一起
  • 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]

编辑

使用 reduce 可能会有点难懂,所以这里有一个更简单的方法:

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

撰写回答