2012-06-04 2 views
6

Ниже приведены два массива:Как работает функция 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) 

выход:

['198.124.252.130', '198.124.252.102'] 

'198.124.252.102' быть не должно ближайший матч для '198.124.252.101'?

Я посмотрел документацию, где они указали о некоторых плавающих типах, но не содержит информации об использовании алгоритма.

Мне нужно найти, если абсолютная разница между двумя последними октетами равна 1 (при условии, что первые три октета одинаковы).

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

Есть ли какая-либо другая функция или способ достижения этого? Также как ведет себя get_close_matches()?

ipaddr похоже, что у таких манипуляций нет.

ответ

6

Ну, есть эта часть в docs объясняя свой вопрос:

Это не дает минимальные редактирования последовательности, но, как правило, дают совпадения, которые «смотрят прямо» к людям.

Для получения результатов вы ожидаете, что сможете использовать Levenshtein_distance.

Но для сравнения IP-адресов, я бы предложил использовать целочисленную сравнения:

>>> 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 

Вы можете использовать этот стиль, чтобы создать функцию сравнения:

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

Спасибо! не совсем то, что я искал, хотя .. Я реализовал пользовательскую логику, чтобы делать то, что мне нужно. – Dexters

1

Некоторые намек от difflib:

SequenceMatcher - это гибкий класс для сравнения пар последовательностей любого типа, если секвенция Элементы хэшируются. Основной алгоритм предшествует, и немного более интересен, чем алгоритм , опубликованный в конце 1980-х годов Ратклиффом и Обершельпом под гиперболическим именем «сопоставление гештальт-шаблонов». Основная идея состоит в том, чтобы найти самую длинную смежную подпоследовательность, которая не содержит «нежелательных» элементов (R-O не адресует мусор). Затем та же идея применяется рекурсивно к частям последовательностей слева и к справа от соответствующей подпоследовательности. Это не приводит к минимальным изменениям последовательностей, но имеет тенденцию давать совпадения, которые «выглядят правильно» для людей.

Относительно вашего требования сравнить IP-адреса на основе пользовательской логики. Вы должны сначала проверить правильность строки. Тогда писать логику сравнения с использованием простой целочисленной арифметики должно быть легкой задачей для выполнения вашего требования. Библиотека вообще не нужна.