Partage
  • Partager sur Facebook
  • Partager sur Twitter

Comptage d’occurrences d'un motif dans un texte

Sujet résolu
    14 août 2015 à 17:31:12

     Bonjour,

    Pour un devoir je dois écrire une fonction qui compte les motifs de trois lettres ou plus qui apparaissent au moins deux fois dans le texte.

    J'ai écris une fonction mais elle ne me renvoie que   [['cou'],[4]]

    def comptage_motif1(texte):
        motifs = []
        occurences = []
        for i in range (len(texte)):
            for j in range (3,len(texte)):
                if i + j < len(texte) and j*2 < len (texte):     #On verifie que tout le motif se trouve dans le texte
                    motif_ref = ''
                    for k in range(j):
                        motif_ref += texte[j+k]
                        k += 1
                    if motif_ref not in motifs and texte.count(motif_ref) >= 2:
                        motifs.append(motif_ref)
                        occurences.append(texte.count(motif_ref))
        tableau = [motifs, occurences]
        return tableau
                        
    print (comptage_motif1('coucouroucou'))

    Merci d'avance
    • Partager sur Facebook
    • Partager sur Twitter
      14 août 2015 à 19:22:53

      Salut, je te propose un code alternatif:

      motif=dict()
      texte="coucouroucou"
      depart=0
      
      for c in range(2, len(texte)-2):
      	base=texte[depart:c]
      	depart+=1
      	
      	#Eviter les doublons.
      	continuer=True
      	for t in range(c, len(texte)):
      		if base+texte[t] in motif:
      			continuer=False
      			break
      	
      	if continuer:
      		#Recherche le nombre d'occurrences pour un motif donné.	
      		for c2 in texte[c:]:
      			base+=c2
      			i,i2=0,0
      			while(i != -1):
      				i=texte[i2:].find(base)
      				if i != -1:
      					if base in motif:
      						motif[base]+=1
      					else:
      						motif[base]=1
      				i2+=i+len(base)
      
      #Sélection des motifs répondant au critère.
      motif_valable=list()
      for m, nbr in motif.items():
      	if nbr >= 2:
      		motif_valable.append([m, nbr])
      	
      print(motif_valable)



      • Partager sur Facebook
      • Partager sur Twitter
        14 août 2015 à 21:37:21

        Bel exercice! :)

        Alors de quoi as-tu besoin? Pour approcher ce genre de problème, ça peut aider de s'imaginer que tu as déjà à ta disposition toutes les fonctions que tu veux, et tu dois juste essayer de les assembler pour arriver à ce que tu désires.

        Pour ton problème, il va falloir couper ta chaîne de caractères en morceaux de longueur données et chaque morceau doit commencer un caractère plus loin que le précédent. Voilà déjà une fonction à faire!

        Donc pour une chaîne "abcdefghi" que tu veux couper en morceaux de 3 caractères, ça donnera en retour["abc", "bcd", "cde", "def", "efg", "fgh", "ghi"].

        Ensuite tu vas devoir pouvoir compter dans une liste de morceaux de chaînes combien de morceaux sont les mêmes. Voilà une deuxième fonction! Il faut te demander sous quel forme tu vas retourner le résultat. Il faut en tout cas deux information par morceau de chaîne: le morceau en question, et le nombre de fois qu'il a été aperçu.

        Finalement il ne te reste plus qu'à couper ta chaîne en un nombre de morceaux allant de 3 jusqu'à la longueur de la chaîne - 1. Pourquoi -1 ? Car si tu prends toute la longueur de la chaîne, elle ne peut pas être comparée à autre chose qu'elle même. :) Ces listes de morceaux coupés, tu vas les passer à ta deuxième fonction qui compte les morceaux les même. Une fois que tu as cet ensemble, tu ne gardes que ceux dont le compte est supérieur ou égal à 2 et tu les ajoutes à une liste de résultat.

        -
        Edité par Dan737 14 août 2015 à 21:41:16

        • Partager sur Facebook
        • Partager sur Twitter
          15 août 2015 à 22:00:20

          C'est bon, j'ai reussi :)

          Merci pour votre aide

          • Partager sur Facebook
          • Partager sur Twitter
            16 août 2015 à 0:21:41

            Ecrire ta solution aurait été sympa pour les prochains. En attendant en voilà une.

            text = "coucouroucou"
            dic_res = {}
            for i in range(len(text)) :
                slice = text[i:i+3]
                if len(slice) < 3 : break
                try : dic_res[slice] += 1
                except KeyError : dic_res[slice] = 1
            
            res = [(key, value) for key, value in dic_res.items() if value > 1]
            print(res)



            • Partager sur Facebook
            • Partager sur Twitter
            Anonyme
              16 août 2015 à 7:19:14

              Solution avec textwrap

              from textwrap import wrap
              
              text = "coucouroucou"
              length = len(text)
              mySet = set()
              
              for i in range(length):
              	listWord = wrap(text[i:], 3)
              	for word in listWord:
              		if len(word) == 3:
              			mySet.add(word)
              
              for res in mySet:
              	n = text.count(res)
              	if n > 1:
              		print('{} -> {}'.format(res, n))

               P.S : Sans regarder, je dirais que celle de Jevanni est très efficace et est beaucoup plus rapide que ma solution

              EDIT:

              @Jevanni,

              On peut sans doute améliorer de l'ordre de 20% à 40% je pense, la rapidité de ton code

              text = "coucouroucou"
              length = len(text)-2
              dic_res = {}
              res = []
                  
              for i in range(length):
                  s = text[i:i+3]
                  if s not in dict_res:
                      dic_res[s] = 1
                  else:
                      dic_res[s] += 1
                  
              myItems = dic_res.items()
              for key, value in myItems:
                  if value > 1:
                      res.append((key, value))
                          
              print(res)

              Eh oui avoir un code plus court ne veut pas dire plus efficace !

              @HSystem,

              Ton code est faux, enfin il ne retourne pas ce que ça devrait faire, par contre il y a du potentiel dans ta démarche pour le rendre plus efficace que Jevanni, à toi de corriger !

              -
              Edité par Anonyme 16 août 2015 à 8:51:26

              • Partager sur Facebook
              • Partager sur Twitter
                16 août 2015 à 10:20:27

                Intéressant ! Je me suis toujours demandé ce qui était le plus gourmand entre le if avec un has_key(), un try/except ou une autre solution tierce. Par contre je ne savais pas qu'une liste compréhension rendait python plus lent. D'ailleurs juste une question, j'ai fait ça sous un terminal python 3 et j'ai l'habitude de python 2. Mais dans la v3 ils ont aussi remplacé iteritems() par items() ?
                • Partager sur Facebook
                • Partager sur Twitter
                  16 août 2015 à 11:01:40

                  Moi je lis l'énoncé:

                  Pour un devoir je dois écrire une fonction qui compte les motifs de trois lettres ou plus qui apparaissent au moins deux fois dans le texte.

                  Alors je peux me tromper mais il faut regarder les groupes de 3 lettres, puis de 4 lettres, etc.

                  J'avais fait deux codes. Un qui est censé être plus abordable, car il utilise moins de concepts plus avancés, mais est bien entendu moins performant et plus gourmand en mémoire. L'autre utilise les itérateurs.

                  Premier code:

                  def n_wise(string, n=2):
                  
                  "s -> (s0s1...sn), (s1s2...sn+1), (s2s3...sn+2), ..."
                  result = []
                  for i in range(len(string)-n+1):
                      result.append(string[i:i+n])
                  return result
                  

                  def count_slices(slices):

                  counter = dict()
                  for string in slices:
                      if string not in counter:
                          counter[string] = 1
                      else:
                          counter[string] += 1
                  return counter
                  

                  def count_patterns(string):

                  result = []
                  for pattern_len in range(3, len(string)):
                      slices = n_wise(string, pattern_len)
                      counter = count_slices(slices)
                      result.extend((pattern, count) for pattern, count in counter.items() if count >= 2)
                  return result
                  

                  if name == 'main':

                  s = "coucouroucou"
                  s = "couaaaaaaaaaaaaouc"
                  print(count_patterns(s))
                  
                  </pre>

                  Et le deuxième plus performant

                  from itertools import tee, repeat, islice
                  from collections import Counter
                  

                  def n_wise(iterable, n=2):

                  "s -> (s0,s1,...,sn), (s1,s2,...,sn+1), (s2, s3,...,sn+2), ..."
                  iterators = tee(iterable, n)
                  start = range(n)
                  stop = repeat(None, n)
                  return zip(*map(islice, iterators, start, stop))
                  

                  def count_patterns(iterable):

                  result = []
                  for pattern_len in range(3, len(iterable)):
                      counter = Counter(map(''.join, n_wise(iterable, pattern_len)))
                      result.extend((pattern, count) for pattern, count in counter.items() if count >= 2)
                  return result
                  

                  if name == 'main':

                  s = "coucouroucou"
                  print(count_patterns(s))
                  
                  </pre>

                  -
                  Edité par Dan737 16 août 2015 à 11:09:15

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Anonyme
                    16 août 2015 à 11:26:24

                    Par contre je ne savais pas qu'une liste compréhension rendait python plus lent

                    Ça ne l'est pas, mais le nombre d'opérations que tu fais dedans est plus importantes que sur une boucle standard...

                    @Dan737,

                    Oui tu as certainement raison, je me suis fixé sur les résultats de Jevanni sans faire attention au problème de départ, ça se trouve du coup que HSystem avait vu juste. :)

                    • Partager sur Facebook
                    • Partager sur Twitter
                      16 août 2015 à 18:24:18

                      Oui désolé, j'ai encore mal lu l'énoncé. J'aime pas mal ta seconde solution Dan.

                      @oldProgrammer : Ah bon ? Car le code ci dessous me semble en tous points identique.

                      res = []
                      myItems = dic_res.items()
                      for key, value in myItems:
                          if value > 1:
                              res.append((key, value))
                      
                      res = [(key, value) for key, value in dic_res.items() if value > 1]



                      • Partager sur Facebook
                      • Partager sur Twitter
                      Anonyme
                        16 août 2015 à 18:46:24

                        @oldProgrammer : Ah bon ? Car le code ci dessous me semble en tous points identique.


                        Effectivement je ne devais pas être très concentré au moment d'écrire cela, cela vient bien de tes premières lignes...

                        • Partager sur Facebook
                        • Partager sur Twitter

                        Comptage d’occurrences d'un motif dans un texte

                        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                        • Editeur
                        • Markdown