[R] Optimisation de code de recherche dans tableau

Aide et conseils concernant AutoIt et ses outils.
Règles du forum
.
Répondre
jpascal
Niveau 6
Niveau 6
Messages : 201
Enregistré le : jeu. 16 oct. 2008 16:21
Status : Hors ligne

[R] Optimisation de code de recherche dans tableau

#1

Message par jpascal »

Bonjour,

Une petite aide pour optimiser du code serait la bienvenue. :-)

Soit un tableau 2D avec :
- dans la première colonne, un numéro allant par exemple de 10000 à 99999
- dans la seconde colonne, les lettres A ou B

Il faut extraire de ce premier tableau, la liste de numéros ayant comme valeur dans la seconde colonne à la fois A et B.
Pour un tableau à 1 000 entrées c'est rapide, pour 10 000 un peu moins. :-(

Il serait peut-être plus judicieux de créer un tableau avec un certain nombre de lignes et de redimensionner à la fin...

Voici le code pour que vous puissiez tester :
#include <Array.au3>

Global $g_aData[0][2]
Global $g_aExtract[0][2]

CreateData()
ExtractNumbersWithAllValues()

Func CreateData()
   Local $bOtherValueCol2 = False

   For $i = 1 To 10000
      $bOtherValueCol2 = False
      $sValueCol1 = Random(10000, 99999, 1)
      For $j = 1 To Random(1, 3, 1)
         _ArrayAdd($g_aData, $sValueCol1 & '|' & ($bOtherValueCol2 ? 'B' : 'A'))
         If $bOtherValueCol2 = False And Random(1, 2, 1) = 2 Then $bOtherValueCol2 = True
         If UBound($g_aData) = 10000 Then ExitLoop 2
      Next
   Next

   _ArrayDisplay($g_aData, "Data")
EndFunc   ;==>CreateData

Func ExtractNumbersWithAllValues()
   Local $aValueA[0]
   Local $iIndex = 0

   Local $hTimer = TimerInit()

   If $g_aData[0][1] = 'A' Then _ArrayAdd($aValueA, $g_aData[0][0])
   For $iRow = 1 To UBound($g_aData) - 1
      If Not (($g_aData[$iRow][0] = $g_aData[$iRow - 1][0]) And ($g_aData[$iRow][1] = $g_aData[$iRow - 1][1])) Then ; pas de vérif si valeurs col0 et col1 identiques à la previous row
         $iIndex = _ArraySearch($aValueA, $g_aData[$iRow][0])
         If $iIndex = -1 Then
            If $g_aData[$iRow][1] = 'A' Then _ArrayAdd($aValueA, $g_aData[$iRow][0]) ; si numéro non présent dans table intermédiaire et valuer col1 = A
         ElseIf $g_aData[$iRow][1] = 'B' Then ; recherche de la valeur A OK (implicite)
            _ArrayAdd($g_aExtract, $g_aData[$iRow][0]) ; ajout dans le tableau définitif
         EndIf
      EndIf
   Next

   cwtimer($hTimer)

   _ArrayDisplay(_ArrayUnique($g_aExtract, 0, 0, 0, $ARRAYUNIQUE_NOCOUNT), "Extraction") ; suppression des doublons
EndFunc   ;==>ExtractNumbersWithAllValues

Func cwtimer($hTimer)
   Local $iTotalSec = Floor(TimerDiff($hTimer) / 1000)
   Local $iMin = Floor($iTotalSec / 60)
   Local $iSec = $iTotalSec - 60 * $iMin
   If $iTotalSec < 10 Then
      ConsoleWrite('Traitement effectué en ' & Floor(TimerDiff($hTimer)) & ' msec' & @CRLF)
   Else
      ConsoleWrite('Traitement effectué en ' & ($iMin > 0 ? $iMin & ' min ' : '') & $iSec & ' sec' & @CRLF)
   EndIf
EndFunc   ;==>cwtimer
Modifié en dernier par jpascal le mar. 11 oct. 2022 17:21, modifié 1 fois.
AutoIt 3.3.16.1 - AutoIt3Wrapper 21.316.1639.1
Avatar du membre
mikell
Modérateur
Modérateur
Messages : 6217
Enregistré le : dim. 29 mai 2011 17:32
Localisation : Deep Cévennes
Status : Hors ligne

Re: [..] Optimisation de code de recherche dans tableau

#2

Message par mikell »

Les fonctions _Array* (add, search, display etc) bouffent des ressources incroyables
L'idéal serait de passer par SQlite, mais à défaut on peut utiliser Scripting.Dictionary

#include <Array.au3>

$sd = ObjCreate("Scripting.Dictionary")
$res = ObjCreate("Scripting.Dictionary")

CreateData()
ExtractNumbersWithAllValues()


Func CreateData()
   Local $bOtherValueCol2 = False
   For $i = 1 To 10000
      $bOtherValueCol2 = False
      $sValueCol1 = Random(10000, 99999, 1)
      For $j = 1 To Random(1, 3, 1)
      $tmp = $sValueCol1 & '|' & ($bOtherValueCol2 ? 'B' : 'A')
      $sd($tmp) = ""
         If $bOtherValueCol2 = False And Random(1, 2, 1) = 2 Then $bOtherValueCol2 = True
         If $sd.count > 10000 Then ExitLoop 2
      Next
   Next

; Msgbox(0,"", "ok")
   ; affichage de l'array facultatif
   ; $g_aData = $sd.Keys()
   ; _ArrayDisplay($g_aData, "Data")
EndFunc   ;==>CreateData


Func ExtractNumbersWithAllValues()
   Local $hTimer = TimerInit()

   For $i In $sd
      $tmp = StringSplit($i, "|", 2)
      $item = $res.exists($tmp[0]) ? $res.item($tmp[0]) : ""
      $res.item($tmp[0]) = $item & $tmp[1]
   Next
   ; $atmp = _list($res)
   ; _ArrayDisplay($atmp, "tmp")
   For $i In $res
      If not ($res.item($i) == "AB") Then $res.remove($i)
   Next
   $g_aExtract = _list($res)

      cwtimer($hTimer)
   _ArrayDisplay($g_aExtract, "extract")
EndFunc   ;==>ExtractNumbersWithAllValues


Func _list($dico)
   Local $keys = $dico.Keys
   Local $items = $dico.Items
   Local $count = $dico.Count
   Local $ret[$count+1][2]
   $ret[0][0] = $count
   For $i = 1 To $count
      $ret[$i][0] = $keys[$i-1]
      $ret[$i][1] = $items[$i-1]
   Next
   Return $ret
EndFunc


Func cwtimer($hTimer)
   Local $iTotalSec = Floor(TimerDiff($hTimer) / 1000)
   Local $iMin = Floor($iTotalSec / 60)
   Local $iSec = $iTotalSec - 60 * $iMin
   If $iTotalSec < 10 Then
      ConsoleWrite('Traitement effectué en ' & Floor(TimerDiff($hTimer)) & ' msec' & @CRLF)
   Else
      ConsoleWrite('Traitement effectué en ' & ($iMin > 0 ? $iMin & ' min ' : '') & $iSec & ' sec' & @CRLF)
   EndIf
EndFunc   ;==>cwtimer
" L'échec est le fondement de la réussite. " (Lao-Tseu )
" Plus ça rate, plus on a de chances que ça marche " (les Shadoks )
jpascal
Niveau 6
Niveau 6
Messages : 201
Enregistré le : jeu. 16 oct. 2008 16:21
Status : Hors ligne

Re: [..] Optimisation de code de recherche dans tableau

#3

Message par jpascal »

Bonjour mikell.

J'ai pensé à SQLite également.

Le résultat obtenu par le script est différent mais j'ai compris la logique. ;-)
Je ne connaissais pas ObjCreate("Scripting.Dictionary").
C'est vraiment le jour et la nuit.

Merci beaucoup.
AutoIt 3.3.16.1 - AutoIt3Wrapper 21.316.1639.1
Avatar du membre
mikell
Modérateur
Modérateur
Messages : 6217
Enregistré le : dim. 29 mai 2011 17:32
Localisation : Deep Cévennes
Status : Hors ligne

Re: [R] Optimisation de code de recherche dans tableau

#4

Message par mikell »

Le résultat a une forme différente (array 2D) parce que j'ai utilisé une fonction _list() pour visualiser le concept
On obtient l'array 1D voulue (et en plus c'est plus rapide) en remplaçant
$g_aExtract = _list($res)
par
$g_aExtract = $res.keys()

Image
" L'échec est le fondement de la réussite. " (Lao-Tseu )
" Plus ça rate, plus on a de chances que ça marche " (les Shadoks )
jpascal
Niveau 6
Niveau 6
Messages : 201
Enregistré le : jeu. 16 oct. 2008 16:21
Status : Hors ligne

Re: [R] Optimisation de code de recherche dans tableau

#5

Message par jpascal »

Non le résultat est différent. :P
Mais ce n'est pas ce qui importe. ;-)

Image Image

En plus je me demande si le problème ne vient pas du fait que j'ai modifié mon code initial (au tout début cependant). :roll:
AutoIt 3.3.16.1 - AutoIt3Wrapper 21.316.1639.1
jpascal
Niveau 6
Niveau 6
Messages : 201
Enregistré le : jeu. 16 oct. 2008 16:21
Status : Hors ligne

Re: [R] Optimisation de code de recherche dans tableau

#6

Message par jpascal »

J'adore les coïncidences.
Je viens d'apprendre l'existence de la commande _Array2DCreate() et l'exemple utilise ObjCreate('scripting.dictionary') :-)
AutoIt 3.3.16.1 - AutoIt3Wrapper 21.316.1639.1
Répondre