Probleme de liste python

Fermé
Poufpaf - Modifié le 27 avril 2022 à 11:02
 Utilisateur anonyme - 2 mai 2022 à 08:09
Bonjour, ce que je cherche à faire est un petir programme permettant de retrouver un mot à partir de lettres dans le mauvais ordre (ex: à partie de "hcta" retrouver "chat" ou tous les autres mots possible). Pour cela, j ai implémenté directement dans le code (pour execution + rapide) une liste de 300000 mots en francais. Ce que mon programme fait, c est à partir d'un (mot dans le mauvais ordre), il retrie la liste des 300000 mots en une sous-liste contenant des mots avec une des lettres contenur dans le (mot dans le mauvais ordre) ensuite il repete l'operation a partir de la sous-liste avec la 2 eme lettre du mot, etc, et ensuite il filltre les mots qui font la bonne taille:
wordstring = """abricot
.......
.......
.......
.......
zython
zythons
zythum
zythums"""

interwordlist = wordstring.splitlines()
wordlistfix = []
for line in interwordlist:
    pureword = str(line.strip())
    wordlistfix.append(pureword)

print(wordlistfix[0:10])


while True:
    badword = str(input("mot à remettre en ordre : "))
    wordlist = wordlistfix
    wordindex = range(int(len(wordlistfix)))
    for lettre in badword:
        selectindex = []
        for index in wordindex:
            word = wordlist[index]
            if lettre in word:
                selectindex.append(index)
                i = word.find(lettre)
                newword = ""
                for n in range(len(word)):
                    if n != i:
                        newword = newword + word[n]
                    else:
                        pass
                wordlist[index] = newword
            else:
                continue
        if len(selectindex) < 1:
            print("aucun mot trouvé")
            break
        else:
            wordindex = selectindex
            continue
    for indexfinal in wordindex:
        if len(wordlistfix[indexfinal]) == len(badword):
            print("  ", wordlistfix[indexfinal])
        else:
            continue


Malgré ce cassage de crâne, le programme renvoie des mots qui n'ont rien avoir comme:
pour "hcat" (qui devrait normallement renvoyer "chat") me renvoie à la place, des mots comme : "lici, licn, loc, obia, oucn, ..... " ce qui ressemble à des morceaux de mots incomplets...

Quelqu'un aurrait il assez de matiere grise pour m'aider à conprendre ce qui ne fonctionne pas dans mon code ? J ai relu plusieurs fois, j ai meme essayé d'appliquer mon code a la main sur papier avec une petite liste, mais je ne comprends vraiment pas ce qui ne joue pas.

Merci d'avance
A voir également:

31 réponses

Utilisateur anonyme
30 avril 2022 à 10:02
Bonjour

Tout marche trés bien, mais il subsiste tout de même 1 seul, le seul et ultime problème : dés qu'il s'agit de mot comportant des accents, comme "è", "é", "à", "î", ô, â, ï,.... alors le code ne retourne rien, mème pour les mots très simple.

C'est parce que quand tu cherche "e", ça n'est ni "é" ni "è" ni "ê", pour l'ordinateur se sont 4 caractères différents, plus précisément, ce sont 4 "e" dont 3 avec un signe diacritique, il y a aussi le ç ou la ñ comme cas connu.

Pour retourner les possibilités quelque soit les signes diacritique, il "suffit" de faire les recherches sur le caractère de base.
https://stackoverflow.com/questions/48445459/removing-diacritical-marks-using-python
0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
Modifié le 30 avril 2022 à 11:37
Comme ça, alors (j'ai ajouté 1 mot avec accent) :
Il faut installer unidecode d'abord

from unidecode import unidecode

dico = ['abricot', 'chat', 'oranges', 'onagres', 'organes', 'rageons', 'épais', 'zython']
dico_no_accents = [unidecode(s) for s in dico]
print(dico_no_accents)

while(True):
    mixed_word = input("\nmot à remettre en ordre (Q)uitter : ")
    if(mixed_word in ['q','Q']): break

    mixed_word_no_accents = unidecode(mixed_word)
    mixed_word_a = ''.join(sorted(mixed_word_no_accents))

    found = False
    for word in dico_no_accents:
        word_a = ''.join(sorted(word))
        if(word_a == mixed_word_a):
            found = True
            print('Trouvé : ', word)

    if(not found): print(mixed_word,'non trouvé ...')
0
Utilisateur anonyme
30 avril 2022 à 11:45
Salut, sauf que là ça va te dire, j’ai trouvé epais alors que le vrai mot c’est épais.

Dans le code posté à 1h18 à la ligne 25, il faut dire que piece vaut word sans accent et ça marche.

Ou alors, dans ton concept, il faut créer un tuple pour chaque entrée du dictionnaire. Un peu comme l’a proposé yg_be.
D’ailleurs sont idée de créer un dictionnary avec comme clé les lettres sans diacritiques dans l’ordre alphabétique pour chaque mot sera je pense le plus rapide en cas de recherche multiple.
0
Un truc comme ça (pas concis du tout ;) ! )

from unidecode import unidecode

class Dictionnaire:
     
    def __init__(self, cle, mot):
        self.laCle = cle
        self.lesMots = []
        self.ajouteMot(mot)
        
    def ajouteMot(self, mot):
        self.lesMots.append(mot)
                    
    def __str__(self):
        return self.laCle + " => {" + " - ".join(self.lesMots) + "}"

def CreerDictionnaire(Mots):
    dico = []
    for mot in Mots:
        cle = "".join(sorted(unidecode(mot)))
        if cle in (d.laCle for d in dico):
            monIndex = [d.laCle for d in dico].index(cle)
            dico[monIndex].ajouteMot(mot)
        else:
            dico.append(Dictionnaire(cle,mot))
    return dico

def ChercheMot(lettres, dico):
    cle = "".join(sorted(unidecode(lettres)))
    if cle in (d.laCle for d in dico):
        monIndex = [d.laCle for d in dico].index(cle) 
        print("les mots sont", dico[monIndex].lesMots)
    else:
        print("pas d'occurences")
        
wordstring = """abricot
chat
chatte
zythons
zythum
zythums
pesai
épais
sépia
oranges
rongeas"""

wordlistfix = wordstring.splitlines()
print("La liste de mots", wordlistfix)

dico = CreerDictionnaire(wordlistfix)
print("Le dictionnaire")
for d in dico:
    print(d)


rep = "Q"

while(True):
    mixed_word = input("\nmot à remettre en ordre (Q)uitter : ")
    if(mixed_word in ['q','Q']): break
    ChercheMot(mixed_word, dico)



ce qui donne
La liste de mots ['abricot', 'chat', 'chatte', 'zythons', 'zythum', 'zythums', 'pesai', 'épais', 'sépia', 'oranges', 'rongeas']
Le dictionnaire
abciort => {abricot}
acht => {chat}
acehtt => {chatte}
hnostyz => {zythons}
hmtuyz => {zythum}
hmstuyz => {zythums}
aeips => {pesai - épais - sépia}
aegnors => {oranges - rongeas}


mot à remettre en ordre (Q)uitter : pasei
les mots sont ['pesai', 'épais', 'sépia']


mot à remettre en ordre (Q)uitter : tata
pas d'occurences


mot à remettre en ordre (Q)uitter : oranges
les mots sont ['oranges', 'rongeas']


mot à remettre en ordre (Q)uitter : 


0
yg_be Messages postés 23535 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 27 avril 2025 1 579
30 avril 2022 à 15:57
bonjour Whismeril,
je pense que tu as créé une liste, pas un dictionnaire.
cela empêche Python d'utiliser les clés pour faire une recherche très rapide.
0
yg_be Messages postés 23535 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 27 avril 2025 1 579 > yg_be Messages postés 23535 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 27 avril 2025
30 avril 2022 à 16:14
Variante avec dictionnaire:
from unidecode import unidecode

class Dictionnaire:
     
    def __init__(self,  mot):
        self.lesMots = []
        self.ajouteMot(mot)
        
    def ajouteMot(self, mot):
        self.lesMots.append(mot)

    def __str__(self):
        return "{" + " - ".join(self.lesMots) + "}"
    
def CreerDictionnaire(Mots):
    dico = {}
    for mot in Mots:
        cle = "".join(sorted(unidecode(mot)))
        if cle in dico.keys():
            dico[cle].ajouteMot(mot)
        else:
            dico[cle]=Dictionnaire(mot)
    return dico

def ChercheMot(lettres, dico):
    cle = "".join(sorted(unidecode(lettres)))
    if cle in dico.keys():
        print("les mots sont", dico[cle].lesMots)
    else:
        print("pas d'occurences")
        
wordstring = """abricot
chat
chatte
zythons
zythum
zythums
pesai
épais
sépia
oranges
rongeas"""

wordlistfix = wordstring.splitlines()
print("La liste de mots", wordlistfix)

dico = CreerDictionnaire(wordlistfix)
print("Le dictionnaire")
for d in dico.keys():
    print(d,"==>",dico[d])


rep = "Q"

while(True):
    mixed_word = input("\nmot à remettre en ordre (Q)uitter : ")
    if(mixed_word in ['q','Q']): break
    ChercheMot(mixed_word, dico)

0
Utilisateur anonyme > yg_be Messages postés 23535 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 27 avril 2025
30 avril 2022 à 17:08
En effet, c'est mon manque de maitrise en Python qui me fait patachonner.
Merci
0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
30 avril 2022 à 13:06
Bah, il suffit de changer la variable dans le print:

from unidecode import unidecode

dico = ['abricot', 'chat', 'oranges', 'onagres', 'organes', 'rageons', 'épais', 'zython']
dico_no_accents = [unidecode(s) for s in dico]
print(dico_no_accents)

while(True):
    mixed_word = input("\nmot à remettre en ordre (Q)uitter : ")
    if(mixed_word in ['q','Q']): break

    mixed_word_no_accents = unidecode(mixed_word)
    mixed_word_a = ''.join(sorted(mixed_word_no_accents))

    found = False
    for word in dico_no_accents:
        word_a = ''.join(sorted(word))
        if(word_a == mixed_word_a):
            found = True
            p = dico_no_accents.index(word)
            print('Trouvé : ', dico[p])

    if(not found): print(mixed_word,'non trouvé ...')
0
Utilisateur anonyme
30 avril 2022 à 13:23
Ha oui aussi
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Merci, la methode de classer par odre alphabétique les caracteres de chaque mot du dicos, puis verifier pour tout autre anagrame en replacant dans l'ordre alphabetique si le resultat figure dans la liste me semble en effet la plus rapide, je ne co aissais pas la methode avec join.

Sinon, pour les accents, vous avez mal compris mon probleme. Je saurais comment faire pour ignorer les accents. Seulement, le problème est un autre : lorsque je mets par exemple badword = "éphélatn", le programme devrait me retourner =>"éléphant" car j'ai bel et bien spécifié les accents. Sauf que non, il me retourne rien, j ai comme l'impression que input() ignore les accents.

On est bien d'accord que badword = "éét" devrait me renvoyer "été", mais non, ça ne fonctionne pas avec tout badword contenant des accents. Pourtant été, éléphant,... sont bien dans la liste.

Je comprends pas
0
Je vais essayer avec unicode
0
unidecode* je voulais dire, je ne connais pas ce mod mais je vais essayer la methode de phil, le problème c'est que je voudrais quand même pouvoir ne pas ignorer les accents, et les utiliser dans mixed word afin que le code me remvoie uniquement le bon mots contenant les meme accents, vous voyez..
0
Utilisateur anonyme
30 avril 2022 à 18:01
En combinant la correction de yg_be et les anagrammes comme l'a proposé Phil à un moment

from unidecode import unidecode
import itertools as it

class Dictionnaire:
     
    def __init__(self,  mot):
        self.lesMots = []
        self.ajouteMot(mot)
        
    def ajouteMot(self, mot):
        self.lesMots.append(mot)

    def __str__(self):
        return "{" + " - ".join(self.lesMots) + "}"
    
def CreerDictionnaire(Mots):
    dico = {}
    for mot in Mots:
        cle = "".join(sorted(unidecode(mot)))
        if cle in dico.keys():
            dico[cle].ajouteMot(mot)
        else:
            dico[cle]=Dictionnaire(mot)
    return dico

def ChercheMot(lettres, dico, ignorerDiacritiques = True):
    cle = "".join(sorted(unidecode(lettres)))
    if cle in dico.keys():
        if ignorerDiacritiques:
            print("en ignorant les diacritiques, les mots sont", dico[cle])
        else:
            anags = set("".join(e) for e in it.permutations(lettres, len(lettres)))
            res = []
            for mot in dico[cle].lesMots:
                if(mot in anags):
                    res.append(mot)                   
            print("en prenant en compte les diacritiques, les mots sont", res)
    else:
        print("pas d'occurences")
        
wordstring = """abricot
chat
chatte
zythons
zythum
zythums
pesai
épais
sépia
oranges
rongeas"""

wordlistfix = wordstring.splitlines()
print("La liste de mots", wordlistfix)

dico = CreerDictionnaire(wordlistfix)
print("Le dictionnaire")
for d in dico:
    print(d)


rep = "Q"

while(True):
    mixed_word = input("\nmot à remettre en ordre (Q)uitter : ")
    if(mixed_word in ['q','Q']): break
    ChercheMot(mixed_word, dico)
    ChercheMot(mixed_word, dico, False)


ce qui donne
La liste de mots ['abricot', 'chat', 'chatte', 'zythons', 'zythum', 'zythums', 'pesai', 'épais', 'sépia', 'oranges', 'rongeas']
Le dictionnaire
abciort
acht
acehtt
hnostyz
hmtuyz
hmstuyz
aeips
aegnors


mot à remettre en ordre (Q)uitter : épais
en ignorant les diacritiques, les mots sont {pesai - épais - sépia}
en prenant en compte les diacritiques, les mots sont ['épais', 'sépia']


mot à remettre en ordre (Q)uitter : epais
en ignorant les diacritiques, les mots sont {pesai - épais - sépia}
en prenant en compte les diacritiques, les mots sont ['pesai']


mot à remettre en ordre (Q)uitter : tata
pas d'occurences
pas d'occurences


mot à remettre en ordre (Q)uitter : oranges
en ignorant les diacritiques, les mots sont {oranges - rongeas}
en prenant en compte les diacritiques, les mots sont ['oranges', 'rongeas']


mot à remettre en ordre (Q)uitter : 

0
Utilisateur anonyme
30 avril 2022 à 18:40
En fait, y'a même plus besoin de la classe
from unidecode import unidecode
import itertools as it

    
def CreerDictionnaire(Mots):
    dico = {}
    for mot in Mots:
        cle = "".join(sorted(unidecode(mot)))
        if cle in dico.keys():
            dico[cle].append(mot)
        else:
            dico[cle]=[mot]
    return dico

def ChercheMot(lettres, dico, ignorerDiacritiques = True):
    cle = "".join(sorted(unidecode(lettres)))
    if cle in dico.keys():
        if ignorerDiacritiques:
            print("en ignorant les diacritiques, les mots sont", dico[cle])
        else:
            anags = set("".join(e) for e in it.permutations(lettres, len(lettres)))
            res = []
            for mot in dico[cle]:
                if(mot in anags):
                    res.append(mot)                   
            print("en prenant en compte les diacritiques, les mots sont", res)
    else:
        print("pas d'occurences")
        
wordstring = """abricot
chat
chatte
zythons
zythum
zythums
pesai
épais
sépia
oranges
rongeas"""

wordlistfix = wordstring.splitlines()
print("La liste de mots", wordlistfix)

dico = CreerDictionnaire(wordlistfix)
print("Le dictionnaire")
for d in dico:
    print("clé '", d, "' => ", dico[d])


while(True):
    mixed_word = input("\nmot à remettre en ordre (Q)uitter : ")
    if(mixed_word in ['q','Q']): break
    ChercheMot(mixed_word, dico)
    ChercheMot(mixed_word, dico, False)
0
yg_be Messages postés 23535 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 27 avril 2025 1 579 > Utilisateur anonyme
30 avril 2022 à 20:33
cela existe parfois, avoir "besoin" d'une classe?
0
yg_be Messages postés 23535 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 27 avril 2025 1 579 > Utilisateur anonyme
30 avril 2022 à 20:39
Si on ignore les diacritiques, ne suffit-il pas de supprimer les utilisations de unidecode?
0
yg_be Messages postés 23535 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 27 avril 2025 1 579 > Utilisateur anonyme
30 avril 2022 à 20:45
c'est une hérésie de faire des permutations pour vérifier si deux mots sont des anagrammes!
0
Utilisateur anonyme > yg_be Messages postés 23535 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 27 avril 2025
30 avril 2022 à 21:10
cela existe parfois, avoir "besoin" d'une classe?

En python, je ne sais pas, mais en C# ou Java, pas le choix tout est objet, donc même si tu n'en écris pas tu en utilises. Du coup, c'est une habitude que j'ai prise. Cela dit, si j'avais mieux chercher comment faire un dictionnaire, je m'en serais passé

Si on ignore les diacritiques, ne suffit-il pas de supprimer les utilisations de unidecode?


Partant d'un dictionnaire constitué sans les diacritiques, ça reste simple de refaire un tri sur les quelques mots obtenus pour ne garder que ceux qui ont les "bons" diacritiques. Y'a moultes façons de trier derrière, là je voulais juste réutiliser la proposition de Phil.
On pourrait aussi constituer un dico de dico.
La première clé est sans diacritique et chaque dico dans cette clé a sa clé avec les diacritiques. Ça serait peut être un peu plus long à constituer mais sans doute plus propre


c'est une hérésie de faire des permutations pour vérifier si deux mots sont des anagrammes!

cf ci dessus...
0
On ne m'a toujours pas répondu, ma question était est-ce qu'on peut utiliser les accents dans le input().

Dans la reponse de Whismeril il peut afficher les resultats soit avec accents, soit sans accents, mais dans le input(), epais est dans les 2 cas sans accents.

Ce que j'ai demandé, c'est comment pouvoir faire fonctionner le programme, tout simplement en considerant les é, è, â,... comme des lettres à part, c'est a dire comment faire pour qu'on puisse par exemple : écrire dans le input : " épsia " (avec l'accent), et que le programme nous renvoie uniquement les anagrames contenant " é ", c'est à dire : => sépia, épais (et c'est tout)

Merci d'avance
0
Utilisateur anonyme
1 mai 2022 à 14:13
Regarde en détail, les résultats du message 46…
0
yg_be Messages postés 23535 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 27 avril 2025 1 579
Modifié le 1 mai 2022 à 14:41
essaie ceci, qui t'affiche ce que tu tapes.
while True:
    print("lu:",input("?"))

cela te permettra de vérifier comment les caractères accentués sont traités sur ton ordi.
0
Ça m'affiche les carratères correctement, é => é, è => è...
0
Utilisateur anonyme
Modifié le 1 mai 2022 à 19:03
Pour résumé, le code que Phil t'as donné au message 28 (donc avant que tu nous embrouille avec les accents) fait exactement ce que tu demandes.



Donc vu que ça marche avec les accents et que tu parles d'un problème d'accent, on comprend l'inverse, et on te propose des solutions sans les accents. Et ça ne te va pas, donc forcément nous sommes un peu perdus.
Donc je te propose une solution qui te donne les 2 résultats en fonction d'un paramètre dans la recherche et donc te laisse le choix de chercher en tenant compte des accents ou pas, à ta guise.
Et ça ne te va toujours pas.

yg_be finit par penser que ton ordinateur a une configuration "anormale" qui expliquerait qu'on ne se comprenne pas sur cette histoire d'accents, mais vu ta dernière réponse, ça n'est pas le cas.

Donc y'a un moment, faut expliquer clairement ce que tu veux, éventuellement faire des captures d'écrans montrant un résultat incorrect en postant le code testé.




0
yg_be Messages postés 23535 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 27 avril 2025 1 579
1 mai 2022 à 22:03
Cela peut-être aussi une différence entre les caractères accentués entrés par input() et ceux entrés dans la source Python.
chars="Thérèse"
th=input("?")
if chars == th:
    print("bien!")
else:
    print("oups!",chars, th)
0
yg_be Messages postés 23535 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 27 avril 2025 1 579
1 mai 2022 à 22:20
ceci marche aussi très bien:
def CreerDictionnaire(Mots):
    dico = {}
    for mot in Mots:
        cle = "".join(sorted(mot))
        if not cle in dico.keys():
            dico[cle]=[]
        dico[cle].append(mot)
    return dico

def ChercheMot(lettres, dico):
    cle = "".join(sorted(lettres))
    if cle in dico.keys():
        print("les mots sont", dico[cle])
    else:
        print("pas d'occurences")
        
wordstring = """abricot
chat
chatte
zythons
zythum
zythums
pesai
épais
sépia
oranges
rongeas"""

wordlistfix = wordstring.splitlines()
print("La liste de mots", wordlistfix)

dico = CreerDictionnaire(wordlistfix)
print("Le dictionnaire")
for d in dico.keys():
    print(d,"==>",dico[d])


rep = "Q"

while(True):
    mixed_word = input("\nmot à remettre en ordre (Q)uitter : ")
    if(mixed_word in ['q','Q']): break
    ChercheMot(mixed_word, dico)
0
Utilisateur anonyme > yg_be Messages postés 23535 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 27 avril 2025
2 mai 2022 à 08:09
Oui, du coup, plus besoin de s’embêter à sortir les diacritiques.
0