2012-06-04 13 views
6

Poniżej znajdują się dwie tablice:Jak działa funkcja python difflib.get_close_matches()?

import difflib 
import scipy 
import numpy 

a1=numpy.array(['198.129.254.73','134.55.221.58','134.55.219.121','134.55.41.41','198.124.252.101'], dtype='|S15') 
b1=numpy.array(['198.124.252.102','134.55.41.41','134.55.219.121','134.55.219.137','134.55.220.45', '198.124.252.130'],dtype='|S15') 

difflib.get_close_matches(a1[-1],b1,2) 

wyjściowa:

['198.124.252.130', '198.124.252.102'] 

shouldnt '198.124.252.102' być najbliższy mecz dla '198.124.252.101'?

Przyjrzałem się dokumentacji, w której podano niektóre wagi zmiennoprzecinkowe, ale brak informacji na temat korzystania z algorytmu.

Potrzebuję ustalić, czy absolutna różnica między dwoma ostatnimi oktetami wynosi 1 (pod warunkiem, że pierwsze trzy oktety są takie same).

Najpierw znajduję najbliższy ciąg, a następnie sprawdzam najbliższy ciąg dla powyższego warunku.

Czy jest jakaś inna funkcja lub sposób, aby to osiągnąć? Również, jak zachowuje się get_close_matches()?

ipaddr wydaje się mieć taką manipulację dla ips.

Odpowiedz

6

Cóż, jest to część w docs wyjaśniając swój problem:

To nie daje minimalne sekwencje edycji, ale nie wydają się wydajność odpowiada, że ​​„wygląda dobrze” do ludzi.

Aby uzyskać oczekiwane wyniki, można użyć Levenshtein_distance.

Ale porównując adresy IP Proponuję użyć porównania całkowita:

>>> parts = [int(s) for s in '198.124.252.130'.split('.')] 
>>> parts2 = [int(s) for s in '198.124.252.101'.split('.')] 
>>> from operator import sub 
>>> diff = sum(d * 10**(3-pos) for pos,d in enumerate(map(sub, parts, parts2))) 
>>> diff 
29 

Można użyć tego stylu do stworzenia porównać funkcję:

from functools import partial 
from operator import sub 

def compare_ips(base, ip1, ip2): 
    base = [int(s) for s in base.split('.')] 
    parts1 = (int(s) for s in ip1.split('.')) 
    parts2 = (int(s) for s in ip2.split('.')) 
    test1 = sum(abs(d * 10**(3-pos)) for pos,d in enumerate(map(sub, base, parts1))) 
    test2 = sum(abs(d * 10**(3-pos)) for pos,d in enumerate(map(sub, base, parts2))) 
    return cmp(test1, test2) 

base = '198.124.252.101' 
test_list = ['198.124.252.102','134.55.41.41','134.55.219.121', 
      '134.55.219.137','134.55.220.45', '198.124.252.130'] 
sorted(test_list, cmp=partial(compare_ips, base)) 
# yields: 
# ['198.124.252.102', '198.124.252.130', '134.55.219.121', '134.55.219.137', 
# '134.55.220.45', '134.55.41.41'] 
+0

Dzięki! nie do końca tego, czego szukałem. Zaimplementowałem niestandardową logikę, aby zrobić to, czego potrzebowałem. – Dexters

1

kilka podpowiedzi z difflib:

SequenceMatcher to elastyczna klasa do porównywania par sekwencji dowolnego typu, o ile sekwencja elementy ence są nieosiągalne. Podstawowy algorytm poprzedza i jest nieco bardziej wytworny niż algorytm opublikowany pod koniec lat 80-tych przez Ratcliffa i Obershelpa pod hiperboliczną nazwą "dopasowywanie wzoru gestaltowego" pod . Podstawową ideą jest znalezienie najdłuższej ciągłej pasującej podciągi, która nie zawiera żadnych "śmieciowych" elementów (R-O nie zajmuje się śmieciami). Ten sam pomysł jest następnie stosowany rekursywnie do fragmentów sekwencji po lewej stronie i do prawej pasującej podciągu. Nie daje to minimalnych sekwencji edycji, ale ma tendencję do tworzenia dopasowań, które "wyglądają dobrze" dla ludzi.

Odnośnie Twojego wymagania porównywania adresów IP w oparciu o niestandardową logikę. Powinieneś najpierw sprawdzić, czy ciąg znaków jest prawidłowy. Wtedy pisanie logiki porównania przy użyciu prostej arytmetyki całkowitej powinno być zadaniem łatwym do spełnienia. Biblioteka wcale nie jest potrzebna.