Python: группировка похожих слов

#python #python-3.x

#python #python-3.x

Вопрос:

Новичок в python, столкнулся с проблемой при выполнении этой задачи: есть список слов, сгруппируйте их по следующим правилам: они похожи, если для формирования 𝗐𝗈𝗋𝖽𝟣 используются только буквы в 𝗐𝗈𝗋𝖽𝟤 , и наоборот, в противном случае это не так.

Например:

 word_list = ['arts', 'rats', 'star', 'tars', 'start', 'pat', 'allergy', 'lager', 'largely', 'regally', 'apt',
             'potters', 'tap', 'bluest', 'tap', 'bluets', 'retraced', 'gallery', 'bustle', 'sublet', 'subtle', 'grab']

output = ['arts', 'rats', 'star', 'tars' and 'start'], [..., ....]

  

Я застрял на несколько часов, как мне с этим справиться?

Комментарии:

1. Что вы пробовали за те часы, что вы застряли? Что вы ожидали от работы и что она сделала вместо этого?

2. Похоже на домашнее задание. Мы здесь, чтобы помочь, пожалуйста, расскажите нам, что вы пробовали?

3. @AruneshSingh это не так, просто задание онлайн-курса, поэтому я подумал о том, что мне нужно создать dict с алфавитом в слове (скажем, arts) и сопоставить aplhabet каждого другого слова с dict. Если значение каждого ключа равно 1, значит, они совпадают. Чего я не знаю, так это того, нужно ли мне повторять этот процесс с каждым другим словом в списке? и как я могу создать список, объединяющий только эти совпадающие слова?

Ответ №1:

collections.defaultdict и frozenset (не могу использовать set , поскольку это было бы изменяемо) предоставляют элегантное решение:

 >>> import collections
>>> word_list = ['arts', 'rats', 'star', 'tars', 'start', 'pat', 'allergy', 'lager', 'largely', 'regally', 'apt',
...              'potters', 'tap', 'bluest', 'tap', 'bluets', 'retraced', 'gallery', 'bustle', 'sublet', 'subtle', 'grab']
>>> groups = collections.defaultdict(set)
>>> for word in word_list:
...     groups[frozenset(word)].add(word)
...
>>> print(groups)
defaultdict(<class 'set'>,
    {
        frozenset({'t', 'a', 's', 'r'}): {'rats', 'start', 'star', 'arts', 'tars'},
        frozenset({'t', 'p', 'a'}): {'pat', 'apt', 'tap'},
        frozenset({'g', 'e', 'y', 'l', 'r', 'a'}): {'allergy', 'gallery', 'largely', 'regally'},
        frozenset({'g', 'e', 'l', 'r', 'a'}): {'lager'},
        frozenset({'o', 'e', 's', 't', 'p', 'r'}): {'potters'},
        frozenset({'b', 'e', 'u', 's', 'l', 't'}): {'sublet', 'subtle', 'bluets', 'bustle', 'bluest'},
        frozenset({'e', 'd', 'c', 't', 'r', 'a'}): {'retraced'},
        frozenset({'g', 'b', 'r', 'a'}): {'grab'},
    })
>>>
  

Комментарии:

1. Написание ответов на вопросы «напишите мой код, пожалуйста» не помогает ни платформе SO, ни людям, задающим вопросы — правильные или нет.

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

Ответ №2:

Вы можете попробовать:

 word_list = ['arts', 'rats', 'star', 'tars', 'start', 'pat', 'allergy', 'lager', 'largely', 'regally', 'apt',
             'potters', 'tap', 'bluest', 'tap', 'bluets', 'retraced', 'gallery', 'bustle', 'sublet', 'subtle', 'grab']

output = {}
def split(word):
    return [char for char in word]

for word in word_list:
    ascending_word = split(word)
    unique = "".join(set(sorted(ascending_word)))
    if unique not in output:
        output[unique] = []
    output[unique].append(word)

print(list(output.values()))
  

Вывод:

 [['arts', 'rats', 'star', 'tars', 'start'], ['pat', 'apt', 'tap', 'tap'], ['allergy', 'largely', 'regal
ly', 'gallery'], ['lager'], ['potters'], ['bluest', 'bluets', 'bustle', 'sublet', 'subtle'], ['retraced
'], ['grab']]
  

Комментарии:

1. в наборе (отсортированном(ascending_word) Я получаю список отсортированных алфавитов в каждом слове, верно? если я ввожу ‘arts’, почему я получаю ‘srat’ в unique вместо ‘arst’?

2. Я хочу, чтобы arst был уникальным, чтобы я мог получить все слова, включая эти символы. Вы можете добавить отладчик и можете проверить..

Ответ №3:

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

Ваша проблема выглядит как группировка анаграмм вместе, но с небольшой оговоркой. У вас может быть допустимая группировка, даже если частота символов не совпадает.
Например, вы сгруппировали rats и start вместе, потому что оба они имеют одинаковый тип символов. Следовательно, ваша проблема теперь сводится к минимальному выяснению, какие все слова имеют похожие символьные композиции.
Существует множество способов продолжить отсюда. Я буду описывать алгоритм:

 loop the list 0..(N-1):
  use char-composition as key and push the entry to a list of the respective bucket
  

состав символов: все уникальные символы в слове отсортированы. Например, rats = arst в качестве ключа.
Следовательно, вы получите все соответствующие слова, сгруппированные в одной корзине, а затем вы можете просто распечатать соответствующий список.