web-dev-qa-db-fra.com

En utilisant Python, trouver des anagrammes pour une liste de mots

Si j'ai une liste de chaînes par exemple:

["car", "tree", "boy", "girl", "arc"...]

Que dois-je faire pour trouver des anagrammes dans cette liste? Par exemple, (car, arc). J’ai essayé d’utiliser boucle for pour chaque chaîne et j’ai utilisé if afin d’ignorer des chaînes de longueurs différentes, mais je ne parviens pas à obtenir le bon résultat. 

Comment puis-je parcourir chaque lettre de la chaîne et la comparer aux autres de la liste dans un ordre différent?

J'ai lu plusieurs questions similaires, mais les réponses étaient trop avancées. Je ne peux rien importer et je ne peux utiliser que des fonctions de base.

14
user1040563

Pour ce faire pour 2 chaînes, vous pouvez le faire: 

def isAnagram(str1, str2):
    str1_list = list(str1)
    str1_list.sort()
    str2_list = list(str2)
    str2_list.sort()

    return (str1_list == str2_list)

Quant à l'itération sur la liste, c'est assez simple

23
Ofir Farchy

Créez un dictionnaire de (Word trié, liste de Word). Tous les mots qui sont dans la même liste sont des anagrammes les uns des autres.

from collections import defaultdict

def load_words(filename='/usr/share/dict/american-english'):
    with open(filename) as f:
        for Word in f:
            yield Word.rstrip()

def get_anagrams(source):
    d = defaultdict(list)
    for Word in source:
        key = "".join(sorted(Word))
        d[key].append(Word)
    return d

def print_anagrams(Word_source):
    d = get_anagrams(Word_source)
    for key, anagrams in d.iteritems():
        if len(anagrams) > 1:
            print(key, anagrams)

Word_source = load_words()
print_anagrams(Word_source)

Ou:

Word_source = ["car", "tree", "boy", "girl", "arc"]
print_anagrams(Word_source)
16
hughdbrown

Une solution consiste à trier le mot que vous recherchez avec des anagrammes (par exemple, à l'aide de sorted), trier l'alternative et la comparer.

Donc, si vous recherchez des anagrammes de 'rac' dans la liste ['car', 'girl', 'tofu', 'rca'], votre code pourrait ressembler à ceci:

Word = sorted('rac')
alternatives = ['car', 'girl', 'tofu', 'rca']

for alt in alternatives:
    if Word == sorted(alt):
        print alt
7
Felix Loether

Triez chaque élément puis recherchez les doublons. Il y a une fonction intégrée pour le tri afin que vous n'ayez rien à importer

4
Christian Alis
def findanagranfromlistofwords(li):
    dict = {}
    index=0
    for i in range(0,len(li)):
        originalfirst = li[index]
        sortedfirst = ''.join(sorted(str(li[index])))
        for j in range(index+1,len(li)):
            next = ''.join(sorted(str(li[j])))
            print next
            if sortedfirst == next:
                dict.update({originalfirst:li[j]})
                print "dict = ",dict
        index+=1

    print dict

findanagranfromlistofwords(["car", "tree", "boy", "girl", "arc"])
1
kinjal patel

Il y a plusieurs solutions à ce problème:

  1. Approche classique

    Considérons d’abord ce qui définit un anagramme: deux mots sont des anagrammes s’ils se composent du même ensemble de lettres et si chaque lettre apparaît exactement le même nombre ou la même heure dans les deux mots. Ceci est essentiellement un histogramme du nombre de lettres de chaque mot. C'est un cas d'utilisation parfait pour la structure de données collections.Counter ( voir docs ). Les algorithmes sont les suivants:

    • Construisez un dictionnaire où les clés seraient des histogrammes et les valeurs seraient des listes de mots comportant cet histogramme.
    • Pour chaque mot construit, utilisez son histogramme et ajoutez-le à la liste qui correspond à cet histogramme.
    • Liste de sortie des valeurs du dictionnaire.

    Voici le code:

    from collections import Counter, defaultdict
    
    def anagram(words):
        anagrams = defaultdict(list)
        for Word in words:
            histogram = Tuple(Counter(Word).items()) # build a hashable histogram
            anagrams[histogram].append(Word)
        return list(anagrams.values())
    
    keywords = ("hi", "hello", "bye", "helol", "abc", "cab", 
                    "bac", "silenced", "licensed", "declines")
    
    print(anagram(keywords))
    

    Notez que la construction de Counter est O(l), tandis que chaque mot est trié par O(n*log(l)) où l est la longueur du mot.

  2. Résolution d'anagrammes à l'aide de nombres premiers

    Il s'agit d'une solution plus avancée, qui repose sur le "caractère unique multiplicatif" des nombres premiers. Vous pouvez vous référer à cet article SO: Comparaison d'anagrammes à l'aide de nombres premiers , et voici un exemple de mise en oeuvre en python .

1
Alexander Zhukov

Solution simple en Python :

def anagram(s1,s2):

    # Remove spaces and lowercase letters
    s1 = s1.replace(' ','').lower()
    s2 = s2.replace(' ','').lower()

    # Return sorted match.
    return sorted(s1) == sorted(s2)
0
Zaid Bhat

J'utilise un dictionnaire pour stocker chaque caractère de chaîne un par un. Ensuite, parcourez la deuxième chaîne et trouvez le caractère dans le dictionnaire. Si c'est le cas, diminuez le nombre de clés correspondantes dans le dictionnaire.

class Anagram:

    dict = {}

    def __init__(self):
        Anagram.dict = {}

    def is_anagram(self,s1, s2):
        print '***** starting *****'

        print '***** convert input strings to lowercase'
        s1 = s1.lower()
        s2 = s2.lower()

        for i in s1:
           if i not in Anagram.dict:
              Anagram.dict[i] = 1
           else:
              Anagram.dict[i] += 1

        print Anagram.dict

        for i in s2:
           if i not in Anagram.dict:
              return false
           else:
              Anagram.dict[i] -= 1

        print Anagram.dict

       for i in Anagram.dict.keys():
          if Anagram.dict.get(i) == 0:
              del Anagram.dict[i]

       if len(Anagram.dict) == 0:
         print Anagram.dict
         return True
       else:
         return False
0
Mr. Wonderful

La plupart des réponses précédentes sont correctes, voici un autre moyen de comparer deux chaînes ..__ Le principal avantage de l’utilisation de cette stratégie par rapport à celle du tri est la complexité espace-temps qui est n log of n

1.Vérifiez la longueur de la chaîne

2. Construire fréquence Dictionnaire et comparer si les deux correspondent, alors nous avons identifié des mots anagramme

def char_frequency(Word):
    frequency  = {}
    for char in Word:
        #if character  is in frequency then increment the value
        if char in frequency:
            frequency[char] += 1
        #else add character and set it to 1
        else:
            frequency[char] = 1
    return frequency 


a_Word ='google'
b_Word ='ooggle'
#check length of the words 
if (len(a_Word) != len(b_Word)):
   print ("not anagram")
else:
    #here we check the frequecy to see if we get the same
    if ( char_frequency(a_Word) == char_frequency(b_Word)):
        print("found anagram")
    else:
        print("no anagram")
0
grepit
import collections

def find_anagrams(x):
    anagrams = [''.join(sorted(list(i))) for i in x]
    anagrams_counts = [item for item, count in collections.Counter(anagrams).items() if count > 1]
    return [i for i in x if ''.join(sorted(list(i))) in anagrams_counts]
0
A.Kot

Cela fonctionne bien: 


def find_ana(l):
    a=[]
    for i in range(len(l)):
        for j in range(len(l)): 
            if (l[i]!=l[j]) and (sorted(l[i])==sorted(l[j])):
                a.append(l[i])
                a.append(l[j])

    return list(set(a))

0
Bhavya Geethika

Celui-ci va vous aider:

En supposant que l'entrée est donnée sous forme de chaînes séparées par des virgules

entrée de la console: abc, bac, voiture, rac, pqr, acb, acr, abc

in_list = list()
in_list = map(str, raw_input("Enter strings seperated by comma").split(','))
list_anagram = list()

for i in range(0, len(in_list) - 1):
    if sorted(in_list[i]) not in list_anagram:
        for j in range(i + 1, len(in_list)):
            isanagram = (sorted(in_list[i]) == sorted(in_list[j]))
            if isanagram:
                list_anagram.append(sorted(in_list[i]))
                print in_list[i], 'isanagram'
                break
0
frp farhan