Использование SequenceMatcher для удаления похожих слов или предложений из списков, сохраняя первую запись, которая похожа: - PullRequest
0 голосов
/ 03 ноября 2018

РЕДАКТИРОВАТЬ: Для тех, кто читает это, я решил свою проблему и нашел решение, которое намного быстрее, чем использование itertools по моей оценке. Моя проблема заключалась в том, что я использовал itertools.combination (), который не сохраняет порядок вашего списка, поэтому, если элемент списка был удален как «b» в моей функции, он никогда не был добавлен как «a» и т. Д.

Несмотря на это, следующее решение было быстрее, чем itertools.permutations (), itertools.combination (), эквивалентный для поддержания порядка списков, в моих тестах для типа проблемы, с которой я столкнулся.

from difflib import SequenceMatcher

def ratios(data):
    d_len = len(data)-1
    list_iter= d_len
    def inner_ratios(paragraph, current_sentence, list_iter):
        output_paragraph = paragraph
        paragraph = paragraph[:list_iter]
        for sentence in paragraph:
            if SequenceMatcher(None, current_sentence, sentence).ratio() > ratio_1:
                output_paragraph.remove(current_sentence)
                return output_paragraph, list_iter - 1
        return output_paragraph, list_iter - 1
    while True:
        data, list_iter = inner_ratios(data, data[list_iter], list_iter)
        if list_iter == 0:
            return data

Используя тот же список предложений, длиной 55, для завершения вышеупомянутой функции требуется 0,5678250789642334 секунды, тогда как при использовании itertools.permutations часы равняются 1,094599723815918.

Я использую time (), а не timeit, так что, возможно, он не точный, но мне кажется, что это значительная разница в скорости.

Надеюсь, что это поможет любому с такой же проблемой, как я.


Ниже приведены две функции. Я изначально сделал второй, потому что это казалось, что это самая простая реализация для достижения желаемый результат, и я хотел проверить, сколько времени потребовалось, чтобы завершить посмотрите, сколько времени меня спасла версия itertools.

Предполагаемый результат для обоих одинаков, и это намерение было сравнить каждое предложение в списке предложений (абзаца) с каждым другое предложение в том же пункте и включить только в выходной те предложения, чье отличие от их сверстников превысило заданное соотношение.

Ситуация с полученными результатами не является опуская что-либо или быть пустым, но вместо этого они оба выполняют цель функции в различной степени в том, что они имеют разной длины вывода и / или выбрать опустить / включить разные результаты, которые действительно смущают меня.

import itertools
from time import time
from difflib import SequenceMatcher
from copy import copy

dt = dt[0:15]
dt_1 = copy(dt)
dt_2 = copy(dt)
ratio_1 = 0.4
maxlen = len(dt)

#Function 1 --------------------------
start = time()
out = list()
save = str()
for a, b in itertools.combinations(dt, 2):
    if a == save:
        continue
    save = str()
    if SequenceMatcher(None, a, b).ratio() > ratio_1:
        save = a
        continue
    if b == dt[maxlen-1]:
        out.append(a)
print(time() - start)

#Function 2 --------------------------
out2 = list()
start = time()
save2 = str()
for x in dt_1:
    for y in dt_2:
        if x == save2:
            continue
        if x == y:
            continue
        save2 = str()
        if SequenceMatcher(None, x, y).ratio() > ratio_1:
            save2 = x
            continue
        if y == dt[maxlen - 1]:
            out2.append(x)
print(time() - start)

Я ценю любое понимание заранее и полностью ожидаю этого решимость вопроса побудить меня к тому, что я не понимаю, что проблема была у меня.

Спасибо!

...