#python #set #permutation
#python #установить #перестановка
Вопрос:
Я новичок в python (более или менее) и борюсь с одной задачей, где мне нужно ввести одно предложение либо с помощью пользовательского ввода, либо любым другим способом лучше / проще (предпочтительно длинным, например «Мы встретились друг с другом вчера», но это не имеет большого значения). Затем выполните итерацию по всем буквам, найдите все возможные буквосочетания указанных слов и найдите совпадения с ними в файле, который состоит из тысяч слов (ок. файл размером 4 мб), каждое слово находится в отдельной строке, вот так:
fun
dog
whatever
coffee
cup
Я использовал itertools.permutations
и попытался использовать set
и intersection
.
Без лишних слов, вот мой код на данный момент:
from itertools import permutations
def alpha_check():
"""check whether a sentence consists of only letters"""
sentence = str.lower(input('Type something in: '))
while not sentence.replace(' ', '').isalpha():
print(f"You typed in {sentence!s}. Only letters A-Z allowed, not case sensitive.")
sentence = input("Please, type something again: ")
return sentence
def file_iter(sentence: str):
my_set = set(line.strip() for line in open('file.txt'))
word_list = set(sentence.split())
for x in word_list:
temp = list(permutations(x))
for f in temp:
print(''.join(f), end=' ') # gets rid of commas etc.
inters = my_set.intersection(f)
return inters
print(file_iter(alpha_check()))
Альфа-проверка меня в данный момент не интересует, я только хотел бы заставить этого монстра работать. В настоящее время он выводит что-то вроде этого, при условии, что я ввожу "map lake"
после запроса:
Type something in: map lake
lake laek lkae lkea leak leka alke alek akle akel aelk aekl klae klea kale kael kela keal elak elka ealk eakl ekla ekal {'l', 'e', 'a', 'k'}
и ожидаемым результатом будут перестановки map
и lake
, а затем найденные пересечения внутри входных данных и файла.
Я много искал в SO и Google. Нашел много информации, но я все равно не смог заставить это работать. Это лучшее, что я придумал.
Также я не прошу полного решения, просто прошу помощи, чтобы понять, что я делаю неправильно и как я могу это решить. Подсказки и т.д.
Спасибо!
Обновить:
def file_iter(sentence):
new_sentence = []
my_set = set(line.strip() for line in open('file.txt'))
word_list = sentence.split()
for words in word_list:
permutation = list(permutations(words))
permute_set = my_set.intersection(["".join(word) for word in permutation])
new_sentence = permute_set.union(word_list)
return print(' '.join(set(new_sentence)))
Это обеспечивает вывод ниже:
Type something in: we met each other
toher ache we haec throe other tem each theor ew met thore
Как я могу разложить их по разным предложениям? Что-то вроде этих строк:
we toher met ache
ew tem haec thore
Ответ №1:
Я предполагаю, что под «найти все возможные буквосочетания указанных слов» вы на самом деле имели в виду перестановки. Если это так, то то, что вы хотите сделать, это сохранить большой список слов в словаре с отсортированными буквами в качестве ключа и списком соответствующих слов (анаграмм) в качестве значений.
Затем вы можете просмотреть слова в предложении и найти запись в словаре (используя отсортированные буквы слова), чтобы получить все анаграммы.
Отсортированные буквы (wordKey) могут служить идентификатором группы для слов, которые являются анаграммами друг друга. Все анаграммы приведут к одному ключу в словаре, поэтому вам не нужно беспокоиться о перестановках.
- lake —(сортировать буквы)—> aekl: [озеро, утечка, капуста]
- утечка —(сортировка букв)—> aekl: [озеро, утечка, капуста]
-
kale —(сортировать буквы)—> aekl: [озеро, утечка, капуста]
Каждое слово попадает в группу анаграмм, к которой оно принадлежит в словаре
Вот пример, на основе которого вы можете создать свое решение:
anagrams = dict()
for word in open("/usr/share/dict/words").read().split("n"):
wordKey = "".join(sorted(word.lower()))
anagrams.setdefault(wordKey,[]).append(word)
sentence = "We met each other yesterday"
for word in sentence.split():
wordKey = "".join(sorted(word.lower()))
print(word, anagrams.get(wordKey,[word]))
На основе словаря слов 235K на моем ноутбуке это приводит к следующему результату:
We ['we']
met ['met']
each ['ache', 'each', 'haec']
other ['other', 'thore', 'throe', 'toher']
yesterday ['yesterday']
Обратите внимание, что ваше решение было близко к рабочему.
f
Переменная вmy_set.intersection(f)
должна была быть,temp
потому чтоf
это просто последняя перестановка.- Также
f
вероятно, содержал не то, что вы ожидали. Посколькуpermutation(x)
обрабатываетсяx
как список, он выдает результат (temp
), который представляет собой список списков, а не список строк. - Поэтому, если вы измените его на
my_set.intersection([ "".join(f) for f in
, это, вероятно, сработает.
temp]) - Это хороший пример того, как выбор значимых имен для ваших переменных помогает избежать ошибок.
- Мне также интересно, действительно ли возврат
inters
после обработки только первого слова из набора предложений — это то, что вы хотели сделать. - Последняя часть напечатанного результата также подозрительна, поскольку она подразумевает, что вы действительно обнаружили пересечение с отдельными буквами слова «утечка». Это будет указывать на то, что ваш файл содержит слова из одной буквы или что вы не читаете его в соответствующей кодировке (например, unicode, читаемый как ascii). Вы должны распечатать
len(my_set)
или первые несколько записейlist(my_set)[:25]
, чтобы убедиться, что там есть слова, а не буквы.
[ОБНОВЛЕНИЕ] Представление выходных данных в виде единого списка слов:
sentence = "We met each other yesterday"
result = []
for word in sentence.split():
wordKey = "".join(sorted(word.lower()))
result = anagrams.get(wordKey,[]) [word]
print(" ".join(set(result)))
# thore each other haec we met throe toher yesterday ache
[UPDATE2] забавные предложения
Если вы хотите поиграть с результатом и построить все предложения, которые можно было бы сформировать с использованием анаграмм, вам нужно будет просмотреть группу анаграмм каждого слова и «умножать» комбинации на каждом шаге:
from itertools import product
from itertools import product
funkySentences = [[]]
for word in sentence.split():
wordKey = "".join(sorted(word.lower()))
alternateWords = anagrams.get(wordKey,[word])
funkySentences = [ s [w] for s,w in product(funkySentences,alternateWords) ]
funkySentences = set(" ".join(fs) for fs in funkySentences)
for fs in funkySentences:
print(fs)
Это выведет:
we met haec throe yesterday
we met haec thore yesterday
we met haec toher yesterday
we met ache toher yesterday
we met haec other yesterday
we met each throe yesterday
we met each toher yesterday
we met ache other yesterday
we met each thore yesterday
we met ache throe yesterday
we met ache thore yesterday
we met each other yesterday
Вы также можете пойти дальше и изменить порядок слов, применяя перестановки к каждому из этих необычных предложений:
from itertools import chain,permutations
yodaSentences = chain(*[permutations(fs.split()) for fs in funkySentences])
yodaSentences = set(" ".join(ys) for ys in yodaSentences)
for ys in yodaSentences:
print(ys)
Это будет напечатано (Yoda speak):
ache we yesterday met other
other haec we met yesterday
yesterday met throe each we
haec throe yesterday met we
we yesterday met haec toher
yesterday we ache met throe
haec yesterday we other met
other yesterday met haec we
met we haec thore yesterday
each we yesterday other met
we ache yesterday other met
yesterday met toher we each
we met yesterday thore ache
... and many more ....
Комментарии:
1. Спасибо за ответ, это многое прояснило для меня. Однако меня это беспокоит: 1. Я проверил и исправил все в своем исходном коде, и теперь он возвращает все найденные пересечения с одним измененным словом, например lake, leak, kale. пока мне нужно несколько слов. Хорошо, что теперь он находит то, что мне нужно, хотя бы для одного слова. 2. Ваш примерный скрипт возвращает key:value (очевидно), но вы сказали, что мне не придется беспокоиться о перестановках. Но это не значит, что это выполнимо без него, я прав? Также мне нравится избегать наборов, слишком много хлопот с ними здесь.
2. Вы получаете только одно слово из-за преждевременного
return inters
. Вам нужно будет создать результирующий набор, представляющий собой объединение этих пересечений, чтобы охватить все слова. Что касается выполнения этого без перестановок, это определенно выполнимо. Это просто вопрос представления выходных данных иначе, чем в моем примере. (Я добавлю пример в свой ответ …)3. Еще раз спасибо. Вопрос решен. Я пошел с перестановками и получил то, что просил. Если вы не возражаете, не могли бы вы помочь мне получить уникальные предложения сейчас, пожалуйста? Я думал о создании словаря, добавлении к ним ключей (входных слов) и значений (переставленных соответствующих слов). это дает мне значения для моих ключей, так же, как в вашем случае (вывод). Похоже, это не сработало, не удается создавать предложения из них в новых строках. Или у меня просто недостаточно знаний о том, как это сделать. Я обновлю свой вопрос с помощью кода, который я получил сейчас.
4. Для этого вам следует добавить задать новый вопрос. Я все равно добавил несколько идей к своему ответу.
5. Большое вам спасибо! Один маленький вопрос: что здесь делает asterisk
chain(*[permutations(fs.split()) for fs in funkySentences])
? Это что-то умножает? Извините за вопрос новичка