Python 如何从列表中删除几乎重复的整数?
我正在用Python解析一些PDF。这些PDF可视地组织成行和列。pdftohtml脚本将这些PDF转换为XML格式,其中充满了没有任何层次结构的松散的Python 如何从列表中删除几乎重复的整数?,python,list,sorting,Python,List,Sorting,我正在用Python解析一些PDF。这些PDF可视地组织成行和列。pdftohtml脚本将这些PDF转换为XML格式,其中充满了没有任何层次结构的松散的标记。然后,我的代码需要将这些标记重新排序为行 由于每个标记都有类似于“top”或“left”坐标的属性,因此我编写了代码将具有相同“top”坐标的项附加到列表中。此列表实际上是一行 我的代码首先在页面上迭代,找到所有唯一的“top”值,并将它们附加到tops列表中。然后,它迭代这个tops列表。对于每个唯一的顶部值,它将搜索具有该“顶部”值的所
标记。然后,我的代码需要将这些
标记重新排序为行
由于每个
标记都有类似于“top”或“left”坐标的属性,因此我编写了代码将具有相同“top”坐标的
项附加到列表中。此列表实际上是一行
我的代码首先在页面上迭代,找到所有唯一的“top”值,并将它们附加到tops列表中。然后,它迭代这个tops列表。对于每个唯一的顶部值,它将搜索具有该“顶部”值的所有项目,并将其添加到行列表中
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)
在这些边缘情况下,我最终得到了如下列表:
[925, 946, 966, 995, 996, 1015, 1035]
我如何调整代码以避免列表中出现“995”和“996”?我想确保当整数之间的距离在1或2以内时,我只得到一个值 - 对列表进行排序,使接近值彼此相邻
- 使用
根据以前的值过滤该值reduce
>>> 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)
- 对列表进行排序,使接近值彼此相邻
- 使用
根据以前的值过滤该值reduce
>>> 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)
@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]
>>>
@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]
>>>
如果您的列表中有
1,2,3,4,5
,您会选择哪一个?1和4?1号和5号?2号和5号?3?在我正在解析的PDF中,行的间距始终至少为20个单位,因此我不认为最终会出现这样的列表。如果列表中有1,2,3,4,5
,您会选择哪一个?1和4?1号和5号?2号和5号?3?在我正在分析的PDF中,行之间的间隔始终至少为20个单位,因此我不认为最终会出现这样的列表。您能在第一个代码示例中介绍一下reduce()行吗?这看起来是我需要的,我只是想了解发生了什么。reduce是这样工作的。它获取第一个值(在本例中是最后一个参数,[]
空列表),然后调用lambda,其中x是该值,y是列表的第一个值。然后,它重复调用,x是上一次调用的结果,y是列表中的下一项。它返回最终结果。例如,reduce(lambda x,y:x+[y],tops,[])
复制tops
如果lambda中的测试内容大于上一个元素+阈值,则只追加y
。这个条件是充分的,因为列表是单调增长的。(len(x)=0
被添加到测试中以说明第一次迭代。)a if条件else b
是python中的三元表示法。如果条件为真,它将返回a,如果条件为假,它将返回b。您能让我看看第一个代码示例中的reduce()行吗?这看起来是我需要的,我只是想了解发生了什么。reduce是这样工作的。它获取第一个值(在本例中是最后一个参数,[]
空列表),然后调用lambda,其中x是该值,y是列表的第一个值。然后,它重复调用,x是上一次调用的结果,y是列表中的下一项。它返回最终结果。例如,reduce(lambda x,y:x+[y],tops,[])
复制tops
如果lambda中的测试内容大于上一个元素+阈值,则只追加y
。这个条件是充分的,因为列表是单调增长的。(len(x)=0
被添加到测试中以说明第一次迭代。)a if条件else b
是python中的三元表示法。如果条件为真,则返回a;如果条件为假,则返回b。del(列表[k-1])
效率极低。您不需要反转
,只需使用范围(len(top)-1,-1,-1)
。如果要使用reverse
,请使用reversed
,它返回迭代器,而不是执行完整的就地反转过程。该问题在1或2个相互之间提到,因此1是不够的。此外,您在1上迭代的项目太多,因为k低至0。(如果您测试的项目相等且所有项目都相等,则返回空列表)此外,您确实不应该命名列表list
。此外,这会修改(就地排序)输入列表。这可能不是想要的效果。(虽然函数名的确表示sort
)del(list[k-1])
效率很低。您不需要反转
,只需使用范围(len(top)-1,-1,-1)
。如果要使用reverse
,请使用reversed
,它返回迭代器,而不是执行完整的就地反转过程。该问题在1或2个相互之间提到,因此1是不够的。此外,您在1上迭代的项目太多,因为k低至0。(如果您测试的项目相等,并且所有项目都相等,那么将返回一个空列表)此外,您真的不应该这样做