Besoin en optimisation de fonction de recherche .find

Gorzyne

XLDnaute Nouveau
Bonjour à tous,

J'utilise la fonction .find pour compter un nombre d'occurences dans un gros corpus (50 000 lignes comptant de 10 à 1000 caractères).

Donc je fais un .findnext, jusqu'à ce que j'ai une erreur, et je passe au suivant

Je dois faire ce traitement sur environ 1.8 millions de tests et le temps de calcul est a vu de nez de plusieurs centaines d'heures. Par ailleurs l'élément cherché est de type "mot1*mot2"

Bien sûr je parallélise l'opération sur plusieurs postes de travail et j'ai bien sûr mis des screenupdating false mais je cherche des idées ou solution pour gagner en temps de calcul.
-> est ce que du VBA Access me permettrait d'aller plus vite ? de combien de x ?
-> est ce qu'en organisant le problème autrement je peux aller plus vite ? par exemple découpage en mots et find mot à mot sans expression régulière ? (split de la ligne avec 1 mot par colonne et .find en option cellule entière) j'ai peur que le find sur tableau soit difficile à gérer...
-> autre idée utiliser une table de codification mot/nombre et "crypter" ma table avec des nombres, avec en premier les mots les + fréquents ? cette solution me paraît sans doute bonne car permettrait de réduire la taille des entrées du corpus et de le débruiter au passage

un petit extrait du code
Code:
While rowcurrent > rowini  'boucle infinie seulement interrompue si erreur
      Selection.FindNext(After:=ActiveCell).Activate
      rowcurrent = ActiveCell.Row
      ThisWorkbook.Sheets("Tableau").Cells(i, j) = ThisWorkbook.Sheets("Tableau").Cells(i, j) + 1 'on incrémente à chaque occurrence trouvée
Wend

N'hésitez pas à poser des questions si c'est un peu confus. Il s'agit vous l'aurez peut être compris d'un sujet de linguistique informatique.

Tout élément bienvenue.
Merci

Gorz'
 
Dernière édition:

Staple1600

XLDnaute Barbatruc
Re : Besoin en optimisation de fonction de recherche .find

Bonsoir à tous

Gorzyne
Si tu pouvais joindre un échantillon représentatif de tes données, on pourrait y voir plus clair et faire des tests
(Un fichier Excel avec une centaine de lignes suffirait)

Suggestion
En passant par des Arrays (tableaux), il est fort possible que le temps de traitement diminue sensiblement.
 

Gorzyne

XLDnaute Nouveau
Re : Besoin en optimisation de fonction de recherche .find

Voici en PJ un extrait du programme

(il faut enlever le " extrait" du titre pour le faire fonctionner)
 

Pièces jointes

  • Combis 0101 0150 extrait.xlsm
    211.7 KB · Affichages: 65
Dernière édition:

Modeste geedee

XLDnaute Barbatruc
Re : Besoin en optimisation de fonction de recherche .find

Bonsour®
Excel est d'abord un Tableur...
VBA n'est qu'une sous section de VB

s'il s'agit d'un fichier texte à l'origine il est évident que tu n'utilises pas le logiciel adéquat ...:rolleyes:

je pencherai plutôt vers un outil utilisant le langage machine ou le langage C

au pire un fichier Batch avec en ligne de commande
l'instruction Find :
FIND [/V] [/C] [/N] [/I] [/OFF[LINE]] "string" [[drive:][path]filename[ ...]]

/V Displays all lines NOT containing the specified string.
/C Displays only the count of lines containing the string.
/N Displays line numbers with the displayed lines.
/I Ignores the case of characters when searching for the string.
/OFF[LINE] Do not skip files with offline attribute set.
"string" Specifies the text string to find.
[drive:][path]filename Specifies a file or files to search.


????
 

Staple1600

XLDnaute Barbatruc
Re : Besoin en optimisation de fonction de recherche .find

Bonsoir Modeste Geedee

au pire un fichier Batch avec en ligne de commande
Pourquoi au pire ? ;)
Moi j'affectionne toujours la console MS-Dos

Sur Seven, on a aussi findstr
Recherche de chaînes de caractères dans les fichiers.

FINDSTR [/B] [/E] [/L] [/R] [/S] [/I] [/X] [/V] [/N] [/M] [/O] [/P]
[/F:fichier] [/C:chaîne] [/G:fichier] [/D:liste de répertoires]
[/A:attributs de couleur] [/OFF[LINE]]
chaînes [[lecteur:][chemin]nom de fichier[ ...]]

/B Recherche l'élément s'il est en début de ligne.
/E Recherche l'élément s'il est en fin de ligne.
/L Recherche les chaînes littéralement.
/R Recherche les chaînes en tant qu'expressions.
/S Recherche les fichiers correspondants dans le répertoire acti
et dans tous ses sous-répertoires.
/I Spécifie que la recherche ne doit pas tenir compte de la cass
/X Affiche les lignes correspondant parfaitement.
/V N'affiche que les lignes non correspondantes.
/N Affiche le numéro de ligne devant chaque ligne correspondante
/M Affiche uniquement le nom des fichiers contenant des chaînes
correspondantes.
/O Affiche le décalage des caractères pour chaque ligne
correspondante.
/P Ignore les fichiers ne contenant pas de caractères affichable
/ OFF[LINE] Ne pas ignorer les fichiers dont l'attribut hors connexion a
été réglé.
/A:attr Spécifie l'attribut de couleur avec 2 chiffres hexadécimaux.
Entrez "color /?".
/F:fichier Lit la liste des fichiers dans le fichier spécifié (/ pour la
console).
/C:chaîne Recherche la chaîne spécifiée littéralement.
/G:fichier Obtient les chaînes à rechercher à partir du fichier spécifié
(/ pour la console).
/D:rép Recherche dans une liste de répertoires délimitée par des
points-virgules.
chaînes Chaînes à rechercher.
[lecteur:][chemin]nom de fichier
Spécifie les fichiers dans lesquels effectuer la recherche.

Utilisez des espaces pour séparer plusieurs chaînes à rechercher, sauf si
l'argument est précédé de /C.
Exemple : 'FINDSTR "bonne journée" x.y' recherche "bonne" ou "journée" dans
le fichier x.y. 'FINDSTR /C:"bonne journée" x.y' recherche "bonne journée"
dans le fichier x.y.

Petit guide des options usuelles :
. Caractère joker = tout caractère
* Répétition : zéro occurrences ou plus du caractère ou de la class
précédents
^ Emplacement : début de ligne
$ Emplacement : fin de ligne
[classe] Classe de caractères : tout caractère du jeu
[^class] Classe inverse : tout caractère n'appartenant pas au jeu
[x-y] Limites : tout caractère dans les limites spécifiées
\x Échappement : utilisation littérale du métacaractère x
\<xyz Emplacement : début du mot
xyz\> Emplacement : fin du mot
 

Gorzyne

XLDnaute Nouveau
Re : Besoin en optimisation de fonction de recherche .find

d'accord donc
1/ je mets mon corpus dans un txt
2/ j'appelle une commande MSDOS depuis vba genre WinShell un truc du genre
ou
2bis/ j'appelle un batch depuis vba avec en entrée ma recherche
3/ je récupère le résultat du batch... sous la forme d'un txt généré ou je peux récupérer directement dans une var vba ?

à vu de nez vous pensez que ça optimiserait par un facteur combien ?
 

Gorzyne

XLDnaute Nouveau
Re : Besoin en optimisation de fonction de recherche .find

Bon j'ai commencé à me plonger dans cette histoire

Je n'ai pas réussi à executer directement findstr dans le shell

Code:
Shell "findstr marcherche Corpus.txt > résultat.txt
CompteLigne résultat

du coup j'ai essayé en créant un fichier batch à chaque recherche
Code:
chemin = "C:\chemin\monscript.bat"
Open chemin For Output As #3
Print #3, "findstr marcherche Corpus.txt > résultat.txt"
Close #3
Shell ("monscript.bat")
CompteLigne résultat

mais au final avec deux opérations d'écriture de fichier je me demande si je vais gagner quoi que ce soit
bref c'est pas encore gagné

sinon autre idée est ce qu'avec un instr je m'en sortirai mieux ? vu qu'il faudrait boucler je suis pas convaincu.. (et est ce que instr accepte les regexp ?)
 

Gorzyne

XLDnaute Nouveau
Re : Besoin en optimisation de fonction de recherche .find

Bon après beaucoup de galères cette méthode ne donne pas un gain de temps appréciable et par ailleurs est plus approximative du fait des caractères unicode. La gestion des espaces entre en conflit avec les expressions régulières et je ne peux faire tous les tests que je voulais.
Pour un gain supérieur de 1 à 10 j'aurai pu faire avec, mais là c'est plutôt un gain de 1 à 2 donc décevant.

Il y a sans doute des manières plus astucieuses de batcher efficacement mais le temps d'acquisition d'une connaissance hypothétique est trop incertain.

Le problème reste donc en suspens. Je vais voir ci-je peux faire un truc un peu méchant par Access

ci joint mon script:

Code:
@echo off
if not exist %1 goto fin
copy %1.txt %1.bat
:fin
findstr %1 "C:\Users\...\Corpus.txt" > "C:\Users\...\resultatbat.txt"
for /f %%a in ('find /v /c "" ^< "C:\Users\...\resultatbat.txt"') do set /a lignes=%%a
echo %1;%lignes% >>  "C:\Users\...\resultat.txt"
 

Staple1600

XLDnaute Barbatruc
Re : Besoin en optimisation de fonction de recherche .find

Bonsoir à tous

Gorzyne
N'hésitez pas à poser des questions si c'est un peu confus.
Il s'agit vous l'aurez peut être compris d'un sujet de linguistique informatique*.
Soit. ;)
1) *: kesako ?

2) Peux-tu, stp, détailler le but de la manœuvre. ?

3) D'où viennent les données sources et quelle est la finalité de la chose en définitive ?

4) A la relecture les questions 2 et 3 se valent peu ou prou, tu peux donc ne pas répondre aux deux ;)

EDITION
:
Pour le 1) j'ai le Dolip**n et la source du mal de crane ;), donc finalement reste une seule question reste en quête de réponse ;)
 
Dernière édition:

Gorzyne

XLDnaute Nouveau
Re : Besoin en optimisation de fonction de recherche .find

C'est bon finalement j'ai suivi ton conseil de passer par un Array, je gagne effectivement beaucoup, gain de temps x10... je pense en rester là, quelques dizaines d'heures de calcul c'est tout à fait acceptable

je compare une liste de 2000 000 d'expressions régulières à un corpus de 50 000 entrées et je souhaite avoir la fréquence de chaque regexp dans le corpus... dans l'idéal il faudrait en parser beaucoup plus mais bon on y va petit à petit

je balaie mes regexp et pour chacune je regarde si elle est présente dans tous le corpus.
Je me disais que j'aurai pu boucler dans l'autre sens, en balayant chaque entrée du corpus et en passant toute les regexp en revue.

Je pense que le temps de calcul doit être similaire, mais l'intérêt est que j'aurai pu constituer ma base de résultats au fur et à mesure, plutôt que d'avoir à attendre d'avoir bouclé sur toutes les regexp... et ensuite ajouter de nouvelles entrées au corpus éventuellement,
mais bon déjà je suis très satisfait avec ces arrays
 

Staple1600

XLDnaute Barbatruc
Re : Besoin en optimisation de fonction de recherche .find

Re

Gorzyne
Pour notre gouverne et pour satisfaire notre curiosité "vbaistique", tu ne comptes pas publier ton code VBA "arrayisé" sur le forum ?
(je dis cela car en ce qui me concerne je suis assez friand de RegExp et aussi parce qu'il est de coutume sur XLD qu'on partage nos savoirs, non ?)
 

Gorzyne

XLDnaute Nouveau
Re : Besoin en optimisation de fonction de recherche .find

Oui alors c'est tout bête

Code:
Dim montab As Variant
montab = Sheets("Corpus").Range("A1:A54222").Value

For i = istart To imax '1463
    For j = 2 To jmax '1463

    deb = Timer
    
    'on ne prend que si vide
    If ThisWorkbook.Sheets("Tableau").Cells(i, j) = "" Then
    ThisWorkbook.Sheets("Tableau").Cells(i, j) = 0
    recherche = "*" & ThisWorkbook.Sheets("Tableau").Cells(i, 1) & "*" & ThisWorkbook.Sheets("Tableau").Cells(1, j) & "*"
    
    nbocc = 1
    For tabi = 1 To 54222
        If montab(tabi, 1) Like recherche Then
            nbocc = nbocc + 1
        End If
    Next tabi
    ThisWorkbook.Sheets("Tableau").Cells(i, j) = nbocc
    DoEvents

    Next j
ThisWorkbook.Save
Next i

solution 2 inverser la boucle sur le corpus et celle sur les regexp à chercher
- on a l'intégralité du résultat (toutes les regexp balayées), l'ajout de nouvelles entrées au corpus peut se faire au fur et à mesure par la suite
à voir si gain de temps (ou plus lent).. peut être un array avec 2 millions d'entrées est plus juste niveau ressources..
 

Discussions similaires

Statistiques des forums

Discussions
312 223
Messages
2 086 407
Membres
103 201
dernier inscrit
centrale vet