2016-02-19 1 views
0

как новый подход к решению моего вызова описал here, я соединил следующее:Уплотненные для цикла поэлементного сравнения списка

from difflib import SequenceMatcher 

def similar(a, b): 
    return SequenceMatcher(None, a, b).ratio() 

diffs =[ 
"""- It contains a Title II provision that changes the age at which workers 
compensation/public disability offset ends for disability beneficiaries from age 65 to full retirement age (FRA).""", 
"""+ It contains a Title II provision that changes the age at which workers 
compensation/public disability offset ends for disability beneficiaries from age 68 to full retirement age (FRA).""", 
"""+ Here's a new paragraph I added for testing."""] 

for s in diffs: 
    others = [i for i in diffs if i != s] 
    for j in others: 
     if similar(s, j) > 0.7: 
      print '"{}" and "{}" refer to the same sentence'.format(s, j) 
      print 
      diffs.remove(j) 
     else: 
      print '"{}" is a new sentence'.format(s) 

Идея заключается в петлю над струнами, и сравнить друг с другие. Если заданная строка считается похожей на другую, удалите другую, в противном случае данная строка будет считаться уникальной строкой в ​​списке.

Вот результат:

"- It contains a Title II provision that changes the age at which workers 
compensation/public disability offset ends for disability beneficiaries from age 65 to full retirement age (FRA)." and "+ It contains a Title II provision that changes the age at which workers 
compensation/public disability offset ends for disability beneficiaries from age 68 to full retirement age (FRA)." refer to the same sentence 


"- It contains a Title II provision that changes the age at which workers 
compensation/public disability offset ends for disability beneficiaries from age 65 to full retirement age (FRA)." is a new sentence 
"+ Here's a new paragraph I added for testing." is a new sentence 

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

Где ошибка в моей логике цикла? Может ли это быть достигнуто без вложенных for s и удаления элементов?

+3

** НЕ ** изменить список в то время как итерация над ним – spicavigo

+0

@spicavigo Правильно. Это очень очевидно. Следовательно, вопрос. – Pyderman

+1

Вы не можете del ete из 'diffs', пока вы все еще повторяете его; он испортит итерацию. Вместо этого скопируйте список различий для удаления и удаления в конце. Кроме того, вы, скорее всего, ускорите свой код, используя 'itertools.combinations' вместо цикла вложенных циклов. – BrenBarn

ответ

1
from difflib import SequenceMatcher 
from collections import defaultdict 

def similar(a, b): 
    return SequenceMatcher(None, a, b).ratio() 

diffs =[ 
"""- It contains a Title II provision that changes the age at which workers 
compensation/public disability offset ends for disability beneficiaries from age 65 to full retirement age (FRA).""", 
"""+ It contains a Title II provision that changes the age at which workers 
compensation/public disability offset ends for disability beneficiaries from age 68 to full retirement age (FRA).""", 
"""+ Here's a new paragraph I added for testing."""] 


sims = set() 
simdict = defaultdict(list) 
for i in range(len(diffs)): 
    if i in sims: 
     continue 
    s = diffs[i] 

    for j in range(i+1, len(diffs)): 
     r = diffs[j] 
     if similar(s, r) > 0.7: 
      sims.add(j) 
      simdict[i].append(j) 


for k, v in simdict.iteritems(): 
    print diffs[k] + " is similar to:" 
    print '\n'.join(diffs[e] for e in v) 
+0

Спасибо. 'Остальное = diff [:]' должно читать 'оставаясь = diffs [:]' хотя. И даже с этим изменением вывод предполагает, что логика не делает то, что она пытается сделать: http://pastebin.com/xQSRjEV5 – Pyderman

+0

Это должно быть 'if not flag' – spicavigo

+0

Сделав копию' diffs' as у вас есть, я думаю, что сохранение '.remove()' в порядке. Но у вас все еще есть опечатка ('diff' /' diffs'), и ваш код по-прежнему не работает, когда эта опечатка исправлена. – Pyderman

0

Вы можете точно узнать, когда он определяет первое предложение является уникальным путем изменения

print '"{}" is a new sentence'.format(s) 

в

print '"{}" and "{}" are different sentences'.format(s,j) 

Это должно помочь вам увидеть, где именно ваш цикл терпит неудачу.

0

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

Когда список имеет нечетное число элементов, последний должен быть обязательно новое предложение.

def extract_modified_and_new(diffs): 
    for z1, z2 in zip(diffs[::2], diffs[1::2]): 
     if similar(z1, z2) > 0.7: 
      print z1, 'is similar to', z2 
      print 
     else: 
      print z1, ' and ', z2, 'are new' 
      print 
    if len(diffs) % 2 != 0: 
      print diffs[-1], ' is new' 
Смежные вопросы