如何合并列表中的项目以避免项目中的重复内容?

How do I merge items from a list avoiding repeated content inside the items?

编辑 4:

我想做的更简单的例子:

我有一个这样的列表:

sentences = ['Hello, how are','how are you','you doing?']

我想把它变成这样的字符串:

sentence = 'Hello, how are you doing?'

感谢任何帮助!

原文post:

我正在尝试从 .pdf 文件中获取突出显示的文本并将其放入具有相同名称的 .docx 文件中。

这是它的代码:

    from typing import List, Tuple

import fitz  # install with 'pip install pymupdf'
import os
from docx import Document


def _parse_highlight(annot: fitz.Annot, wordlist: List[Tuple[float, float, float, float, str, int, int, int]]) -> str:
    points = annot.vertices
    quad_count = int(len(points) / 4)
    sentences = []
    for i in range(quad_count):
        # where the highlighted part is
        r = fitz.Quad(points[i * 4: i * 4 + 4]).rect

        words = [w for w in wordlist if fitz.Rect(w[:4]).intersects(r)]
        sentences.append(" ".join(w[4] for w in words))
    sentence = " ".join(sentences)
    return sentence


def handle_page(page):
    wordlist = page.getText("words")  # list of words on page
    wordlist.sort(key=lambda w: (w[3], w[0]))  # ascending y, then x
    separator = "PÁGINA NÚMERO " + str(page.number) + ": "

    highlights = []
    annot = page.firstAnnot
    while annot:
        if annot.type[0] == 8:
            highlights.append(separator)
            highlights.append(_parse_highlight(annot, wordlist))
            document.add_paragraph(highlights)
        annot = annot.next

    return highlights


def main(filepath: str) -> List:
    doc = fitz.open(filepath)

    highlights = []
    for page in doc:
        highlights += handle_page(page)

    return highlights

dir_files = [f for f in os.listdir(".") if os.path.isfile(os.path.join(".", f))]
print(dir_files)
document = Document()
for file in dir_files:  # look at every file in the current directory
    if file.endswith('.pdf'):  # if it is a PDF, use it
        print('Working on converting: ' + file)

        main(file)
        document.save(file.replace(".pdf",".docx"))

我不得不说我没有写让文字突出显示的部分。我知道了 here.

问题是它创建的列表有重复项。这是 .docx 文件的输出示例:

PÁGINA NÚMERO 0: En los primeros tiempos de la microscopia electronica los bi- logos pensaban que los organulos de una célula eucarionte primeros tiempos de la microscopia electronica los bi- logos pensaban que los organulos de una célula eucarionte flota- ban libremente en el citosol. Pero los progresos realizados pensaban que los organulos de una célula eucarionte flota- ban libremente en el citosol. Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia en el citosol. Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia electronica han revelado la presencia del citoesqueleto, una red de fibras microscopia 6ptica como en la microscopia electronica han revelado la presencia del citoesqueleto, una red de fibras que se extiende a través del citoplasma (fig. 6-20). El citoesqueleto, revelado la presencia del citoesqueleto, una red de fibras que se extiende a través del citoplasma (fig. 6-20). El citoesqueleto, que desempena un papel importante en la organizacion a través del citoplasma (fig. 6-20). que desempena un papel importante en la organizacion estructuras y las actividades de la célula, PÁGINA NÚMERO 0: En los primeros tiempos de la microscopia electronica los bi- logos pensaban que los organulos de una célula eucarionte primeros tiempos de la microscopia electronica los bi- logos pensaban que los organulos de una célula eucarionte flota- ban libremente en el citosol. Pero los progresos realizados pensaban que los organulos de una célula eucarionte flota- ban libremente en el citosol. Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia en el citosol. Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia electronica han revelado la presencia del citoesqueleto, una red de fibras microscopia 6ptica como en la microscopia electronica han revelado la presencia del citoesqueleto, una red de fibras que se extiende a través del citoplasma (fig. 6-20). El citoesqueleto, revelado la presencia del citoesqueleto, una red de

如您所见,它多次重复同一件事。

我认为这是因为我的 pdf 像这样被分成两部分:

但是将每一页分成两半并创建更长的 pdf 会很不方便。另一个问题可能是我对这个 pdf 进行了 OCR,也许它导致了问题(这就是为什么文本输出与 pdf 略有不同,但我同意)。

所以我正在寻找一种方法来检查“突出显示”列表是否有重复项并将其删除。或者在将它们添加到列表之前进行检查,而不是添加它们。但是我在编程方面没有那么丰富的经验,所以我请求你的帮助!

感谢任何帮助!

抱歉英语不好!

编辑 1:

我现在尝试这样做:

...
def main(filepath: str) -> List:
    doc = fitz.open(filepath)

    highlights = []
    for page in doc:
        highlights += handle_page(page)
        highlights = set(highlights)
        highlights = list(highlights)
        document.add_paragraph(highlights)

    return highlights
...

但它不起作用。它甚至会更改项目的顺序,因为它会删除首先添加的内容,而我不希望这样。

编辑 2:

我想我找到了给我带来麻烦的原因。

在他们加入“句子”之前我做了 print(sentences),这就是我得到的:

['En los primeros tiempos de la microscopia electronica los bi- logos pensaban que los organulos de una célula eucarionte', 'primeros tiempos de la microscopia electronica los bi- logos pensaban que los organulos de una célula eucarionte flota- ban libremente en el citosol. Pero los progresos realizados', 'pensaban que los organulos de una célula eucarionte flota- ban libremente en el citosol. Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia', 'en el citosol. Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia electronica han revelado la presencia del citoesqueleto, una red de fibras', 'microscopia 6ptica como en la microscopia electronica han revelado la presencia del citoesqueleto, una red de fibras que se extiende a través del citoplasma (fig. 6-20). El citoesqueleto,', 'revelado la presencia del citoesqueleto, una red de fibras que se extiende a través del citoplasma (fig. 6-20). El citoesqueleto, que desempena un papel importante en la organizacion', 'a través del citoplasma (fig. 6-20). que desempena un papel importante en la organizacion estructuras y las actividades de la célula,']

如您所见,“句子”中的项目相互包含,所以即使我使用 set(sentences) 它也不起作用。我很确定 OCR 与此有关。

所以现在我想我需要将注意力转移到交叉引用“句子”中的每个项目上。

比如A+B-(A∩B)=C。这意味着 C 不会有重复,如果顺序正确,就会构成一个易于理解的句子。但是我完全不知道是否有办法做到这一点。

我还学会了这个来消除欺骗并仍然保持列表的顺序:list(dict.fromkeys())

编辑 3:

只运行这段代码:

def _parse_highlight(annot: fitz.Annot, wordlist: List[Tuple[float, float, float, float, str, int, int, int]]) -> str:
    points = annot.vertices
    quad_count = int(len(points) / 4)
    sentences = []
    for i in range(quad_count):
        # where the highlighted part is
        r = fitz.Quad(points[i * 4: i * 4 + 4]).rect

        words = [w for w in wordlist if fitz.Rect(w[:4]).intersects(r)]
        sentences.append(" ".join(w[4] for w in words))
    print(sentences)
    sentence = " ".join(sentences)
    print(sentence)
    return sentence


def handle_page(page):
    wordlist = page.getText("words")  # list of words on page
    wordlist.sort(key=lambda w: (w[3], w[0])) 
    separator = "PÁGINA NÚMERO " + str(page.number) + ": "

    highlights = []
    annot = page.firstAnnot
    while annot:
        if annot.type[0] == 8:
            highlights.append(separator)
            highlights.append(_parse_highlight(annot, wordlist))
        annot = annot.next
    return highlights


def main(filepath: str) -> List:
    doc = fitz.open(filepath)

    highlights = []
    for page in doc:
        highlights += handle_page(page)
    print(highlights)
    return highlights

main(example.pdf)

这是我唯一强调的:

终端显示如下:

['El citoesqueleto es una red de fibras que organiza las estructuras', 'citoesqueleto es una red de que organiza las estructuras y las actividades', 'las estructuras y las actividades de la célula', 'En los primeros tiempos de la microscopia electronica los bi- logos pensaban que los organulos de una célula eucarionte', 'primeros tiempos de la microscopia electronica los bi- logos pensaban que los organulos de una célula eucarionte flota- ban libremente en el citosol. Pero los progresos realizados', 'pensaban que los organulos de una célula eucarionte flota- ban libremente en el citosol. Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia', 'en el citosol. Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia electronica han revelado la presencia del citoesqueleto, una red de fibras', 'microscopia 6ptica como en la microscopia revelado la presencia del citoesqueleto, extiende a través del citoplasma']

El citoesqueleto es una red de fibras que organiza las estructuras citoesqueleto es una red de que organiza las estructuras y las actividades las estructuras y las actividades de la célula En los primeros tiempos de la microscopia electronica los bi- logos pensaban que los organulos de una célula eucarionte primeros tiempos de la microscopia electronica los bi- logos pensaban que los organulos de una célula eucarionte flota- ban libremente en el citosol. Pero los progresos realizados pensaban que los organulos de una célula eucarionte flota- ban libremente en el citosol. Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia en el citosol. Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia electronica han revelado la presencia del citoesqueleto, una red de fibras microscopia 6ptica como en la microscopia revelado la presencia del citoesqueleto, extiende a través del citoplasma

['PÁGINA NÚMERO 0: ', 'El citoesqueleto es una red de fibras que organiza las estructuras citoesqueleto es una red de que organiza las estructuras y las actividades las estructuras y las actividades de la célula En los primeros tiempos de la microscopia electronica los bi- logos pensaban que los organulos de una célula eucarionte primeros tiempos de la microscopia electronica los bi- logos pensaban que los organulos de una célula eucarionte flota- ban libremente en el citosol. Pero los progresos realizados pensaban que los organulos de una célula eucarionte flota- ban libremente en el citosol. Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia en el citosol. Pero los progresos realizados tanto en la microscopia 6ptica como en la microscopia electronica han revelado la presencia del citoesqueleto, una red de fibras microscopia 6ptica como en la microscopia revelado la presencia del citoesqueleto, extiende a través del citoplasma']

现在我看到一些我没有突出显示的文本也被变成了一个“句子”项目。同样,我认为这是 OCR 的错误,或者我可以更好地调整 pymupdf idk。

您可以使用 python set 来删除重复项。它应该在循环之后和 return

之前完成
highlights = ['h1', 'h2', 'h1']
no_dups_highlights = list(set(highlights))
print(no_dups_highlights)

输出

['h2', 'h1']

所以set洗牌成员;你可以使用它,但只能作为一个帮手。

有几种方法可以做到这一点:

  • 使用 set 记录您已经看过的内容:
seen = set()
filtered = []
for highlight in highlights:
    if highlight not in seen:
        filtered.append(highlight)
        seen.add(highlight)
  • 如果您使用的是足够新的 Python 版本,dict 维持秩序:
filtered = list({highlight: None for highlight in highlights}.keys())
  • 忽略理论上的慢,直接用最直接的方式编码;它在实践中可能足够快:
filtered = []
for highlight in highlights:
    if highlight not in filtered:
        filtered.append(higwhlight)

以上都是精确匹配;如果您最终需要近似匹配,您可能不得不使用最后一种方法,并使用某种相似性度量。

我已经实现了另一种从 pdf 中获取 'sentences' 列表的方法,现在它可以正常工作了。

这是代码:

from typing import List, Tuple

import fitz
import os
from docx import Document

_threshold_intersection = 0.9

def _check_contain(r_word, points):
    r = fitz.Quad(points).rect
    r.intersect(r_word)

    if r.getArea() >= r_word.getArea() * _threshold_intersection:
        contain = True
    else:
        contain = False
    return contain


def _parse_highlight(annot: fitz.Annot, wordlist: List[Tuple[float, float, float, float, str, int, int, int]]) -> str:
    quad_points = annot.vertices
    quad_count = int(len(quad_points) / 4)
    sentences = ['' for i in range(quad_count)]

    for i in range(quad_count):
        points = quad_points[i * 4: i * 4 + 4]
        words = [
            w for w in wordlist if
            _check_contain(fitz.Rect(w[:4]), points)
        ]
        sentences[i] = ' '.join(w[4] for w in words)
    sentence = ' '.join(sentences)
    document.add_paragraph(sentence)
    return sentence

def handle_page(page):
    wordlist = page.getText("words")
    wordlist.sort(key=lambda w: (w[3], w[0]))

    highlights = []
    annot = page.firstAnnot
    while annot:
        if annot.type[0] == 8:
            highlights.append(_parse_highlight(annot, wordlist))
        annot = annot.next

    return highlights

def main(filepath: str) -> List:
    doc = fitz.open(filepath)

    highlights = []
    for page in doc:
        document.add_paragraph("Page Number " + str(page.number+1) + ": ")
        highlights += handle_page(page)

    return highlights

dir_files = [f for f in os.listdir(".") if os.path.isfile(os.path.join(".", f))]
document = Document()
for file in dir_files:
    if file.endswith('.pdf'):
        print('Working on converting: ' + file)
        main(file)
        document.save(file.replace(".pdf",".docx"))

得到这个新方法here