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

Python 如何从列表中删除几乎重复的整数?,python,list,sorting,Python,List,Sorting,我正在用Python解析一些PDF。这些PDF可视地组织成行和列。pdftohtml脚本将这些PDF转换为XML格式,其中充满了没有任何层次结构的松散的标记。然后,我的代码需要将这些标记重新排序为行 由于每个标记都有类似于“top”或“left”坐标的属性,因此我编写了代码将具有相同“top”坐标的项附加到列表中。此列表实际上是一行 我的代码首先在页面上迭代,找到所有唯一的“top”值,并将它们附加到tops列表中。然后,它迭代这个tops列表。对于每个唯一的顶部值,它将搜索具有该“顶部”值的所

我正在用Python解析一些PDF。这些PDF可视地组织成行和列。pdftohtml脚本将这些PDF转换为XML格式,其中充满了没有任何层次结构的松散的
标记。然后,我的代码需要将这些
标记重新排序为行

由于每个
标记都有类似于“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。(如果您测试的项目相等,并且所有项目都相等,那么将返回一个空列表)此外,您真的不应该这样做