2 votes

Trouver le semordnilap (anagramme inversé) des mots dans une chaîne de caractères

J'essaie de prendre une chaîne en entrée, comme une phrase, et de trouver tous les mots qui ont leur inverse dans la phrase. J'ai ceci jusqu'à présent :

s = "Although he was stressed when he saw his desserts burnt, he managed to stop the pots from getting ruined"

def semordnilap(s):
    s = s.lower()
    b = "!@#$,"
    for char in b:
        s = s.replace(char,"")
    s = s.split(' ')

    dict = {}
    index=0
    for i in range(0,len(s)):
        originalfirst = s[index]
        sortedfirst = ''.join(sorted(str(s[index])))
        for j in range(index+1,len(s)):
            next = ''.join(sorted(str(s[j])))
            if sortedfirst == next:
                dict.update({originalfirst:s[j]})
        index+=1

    print (dict)

semordnilap(s)

Cela fonctionne donc en grande partie, mais si vous l'exécutez, vous pouvez voir qu'il associe également "he" et "he" comme anagramme, mais ce n'est pas ce que je recherche. Si vous avez des suggestions sur la façon de corriger cela, et aussi s'il est possible de rendre le temps d'exécution plus rapide, si je devais entrer un grand fichier texte à la place.

1voto

benvc Points 7028

Vous pourriez diviser la chaîne en une liste de mots, puis comparer les versions en minuscules de toutes les combinaisons où l'une des paires est inversée. L'exemple suivant utilise re.findall() pour diviser la chaîne en une liste de mots et itertools.combinations() pour les comparer :

import itertools
import re

s = "Although he was stressed when he saw his desserts burnt, he managed to stop the pots from getting ruined"

words = re.findall(r'\w+', s)
pairs = [(a, b) for a, b in itertools.combinations(words, 2) if a.lower() == b.lower()[::-1]]

print(pairs)
# OUTPUT
# [('was', 'saw'), ('stressed', 'desserts'), ('stop', 'pots')]

EDIT : Je préfère toujours la solution ci-dessus, mais selon votre commentaire concernant le fait de faire cela sans importer aucun paquet, voir ci-dessous. Cependant, notez que str.translate() utilisé de cette façon peut avoir des conséquences inattendues en fonction de la nature de votre texte (comme la suppression de l'adresse de l'utilisateur). @ des adresses électroniques) - en d'autres termes, il se peut que vous deviez traiter la ponctuation avec plus de soin que cela. En outre, je voudrais généralement import string et utiliser string.punctuation plutôt que la chaîne littérale de caractères de ponctuation que je transmets à str.translate() mais nous avons évité de le faire ci-dessous, conformément à votre demande de faire cela sans importations.

s = "Although he was stressed when he saw his desserts burnt, he managed to stop the pots from getting ruined"

words = s.translate(None, '!"#$%&\'()*+,-./:;<=>?@[\]^_`{|}~').split()
length = len(words)
pairs = []
for i in range(length - 1):
    for j in range(i + 1, length):
        if words[i].lower() == words[j].lower()[::-1]:
            pairs.append((words[i], words[j]))

print(pairs)
# OUTPUT
# [('was', 'saw'), ('stressed', 'desserts'), ('stop', 'pots')]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X