如何从列表中去除几乎重复的整数?
我正在用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)