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

У меня есть 'collections.defaultdict' (см. x ниже), который является многозначным словарем. Все значения, связанные с каждым уникальным ключом, хранятся в списке.

    >>>x
    defaultdict(<type 'list'>, {'a': ['aa', 'ab', 'ac'], 'b': ['ba', 'bc'], 'c': ['ca', 'cb', 'cc', 'cd']})

Я хочу использовать пакет Python fuzzywuzzy для поиска целевой строки по всем значениям, вложенным в многозначный словарь, и возвращать 5 лучших совпадений на основе встроенной формулы расстояния редактирования fuzzywuzzy.

    from fuzzywuzzy import fuzz
    from fuzzywuzzy import process
    query = 'bc'
    choices = x
    result = process.extract(query, choices, limit=5)

Затем я запускаю процесс, который берет самое близкое совпадение (значение с наивысшим коэффициентом нечеткости) и определяет, с каким ключом связано это самое близкое соответствие. В этом примере ближайшим совпадающим значением, конечно же, является «bc», а связанным с ним ключом является «b».

Мой вопрос: как мне запустить fuzzywuzzy-запрос ко всем значениям во вложенных списках словаря? Когда я запускаю описанный выше процесс fuzzywuzzy, я получаю ошибку TypeError: ожидаемая строка или буфер.


person Philosopher    schedule 03.02.2016    source источник


Ответы (2)


Чтобы получить все значения в списках из вашего словаря в плоском списке, используйте
from itertools import chain и измените строку

choices = x

to

choices = chain.from_iterable(x.values())

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

результат:

[('bc', 100), ('ba', 50), ('ca', 50), ('cb', 50), ('cc', 50)]
person timgeb    schedule 03.02.2016

Вы можете сделать это следующим образом:

from fuzzywuzzy import process
from collections import defaultdict

x = defaultdict(list, {'a': ['aa', 'ab', 'ac'], 'b': ['ba', 'bc'], 'c': ['ca', 'cb', 'cc', 'cd']})
query = 'bc'
reverse = defaultdict(list)

for k1, v1 in x.items():
    for v2 in v1:
        reverse[v2].append(k1)

match = process.extractOne(query, chain.from_iterable(x.values()))

print match[0]
print reverse[match[0]]

Это будет отображать:

bc
['b']

Сначала он создает инверсию вашего словаря, чтобы упростить поиск записи, которая соответствует fuzzywuzzy. Затем он создает список всех значений и передает его в extractOne. Затем возвращенное совпадение можно найти в обратном словаре, чтобы отобразить список всех ключей, содержащих совпадение. Если bc было найдено более чем в одном из ваших списков, он отобразит их все.

person Martin Evans    schedule 03.02.2016