Sign in to follow this  
Followers 0
Eugenii

_ArrayBinarySearch&identical elements & Output from running console & _FileListToArray net path restrictions

9 posts in this topic

#1 ·  Posted (edited)

Hello!

1 Closed) Am I right that _ArrayBinarySearch needs that every element in a sorted array had a unique binary (and in most cases usual string) representation? So if I have two or more identical string elements, e.g. "2007/08/01" and "2007/08/01" (which must have identical binary represent. as I think), function will produce unexpected results?

#include <Array.au3>
;
Local $avArray[21]=["2007/09/30", _
"2007/09/30", _
"2007/10/01", _
"2007/10/05", _
"2007/10/05", _
"2008/01/03", _
"2008/01/03", _
"2008/01/03", _
"2008/01/03", _
"2008/01/03", _
"2008/01/03", _
"2008/01/03", _
"2008/04/27", _
"2008/04/27", _
"2008/04/27", _
"2008/11/11", _
"2008/11/30", _
"2008/11/30", _
"2008/11/30", _
"2009/03/17", _
"2009/03/17"]
_ArrayDisplay($avArray,"before")
_ArraySort($avArray)
_ArrayDisplay($avArray,"after") ;nothing changed, array data has been already entered in ascending order
;
$wz=0
$indBS=0
While $indBS<>-1
     $indBS=_ArrayBinarySearch($avArray,"2008/01/03",$wz)
     If $indBS<>-1 Then MsgBox(0,"1",$indBS&" "&$avArray[$indBS])
     $wz=$indBS+1
WEnd

In this code function finds only 10 and 11 elements. So I have to use slower _ArraySearch?

2 Closed) And another arrays question: Do _ArrayDelete and _ArrayAdd have a big influence on speed while working with 1D or 2D array like [3500] Or [3500][2]?

3) Now question about console windows. Is there an way to get output from console window, which is already executed. I also don't like using Run function with $STDOUT_CHILD flag, because it hide console program output from the user, while I need a possibility to manual interact with console without restarting it.

Is it the only right way? :

;Select all text and copy it from the console
Func ConsoleC()
     ;Get it's center
     $wp=WinGetPos($wh)
     MouseClick("right",($wp[0]+($wp[2]/2)),($wp[1]+($wp[3]/2)),1,0)
     Sleep(100)
     SendP("ы")
     SendP("{ENTER}")
     Return ClipGet()
EndFunc
;Check console for specified output
Func CheckC($outp)
     While StringInStr(ConsoleC(),$outp)=0
         Sleep(300)
     WEnd
EndFunc

It utilizes mouse right click, then "select all" command, then send ENTER to copy selected text and in the end it checks this string for requested data.

4) And last question: Are there any restrictions while using _FileListToArray with $sPath=folder at a linked net disk? I use it for getting list of all files with defined extension in specified folder and it's subfolders. It seems to work fine on my internal hdd with 10 subfolders and about 100 files at all, while connected net disk have about 30 folders and each folder may include more than 1000-1500 files (but with right extension only 15-25 files).

THANKS a lot!

Edited by Eugenii

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

The is the way binary search works. http://en.wikipedia.org/wiki/Binary_search_algorithm

Your array is of length 21, so probably the first point in the binary search interval searched is 10. This matches so you update the value to 10+1 = 11 to start.. So next value you find is 11. Afterwards you missed all the previous values. I think what you should do is to use binary search once. Then look to the left and right of the found index for more values. Note that its sorted, so you can just go from index 10 to 9 in your example and keep checking if its equal. that's performance technical the best. If its a small array just a simple array search would just work fine as well.

Edited by cageman

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

cageman,

Thanks, one question is closed. Three more left.

Working code:

#include <Array.au3>
#include <Date.au3>
#include <String.au3>

Local $avArray[21]=["2007/09/30", _ ;0
"2007/09/30", _ ;1
"2007/10/01", _ ;2
"2007/10/05", _ ;3
"2007/10/05", _ ;4
"2008/01/03", _ ;5
"2008/01/03", _ ;6
"2008/01/03", _ ;7
"2008/01/03", _ ;8
"2008/01/03", _ ;9
"2008/01/03", _ ;10
"2008/01/03", _ ;11
"2008/04/27", _ ;12
"2008/04/27", _ ;13
"2008/04/27", _ ;14
"2008/11/11", _ ;15
"2008/11/30", _ ;16
"2008/11/30", _ ;17
"2008/11/30", _ ;18
"2009/03/17", _ ;19
"2009/03/17"] ;20
_ArraySort($avArray)

$iStart=""
$iEnd=""
$indBS=0
$indBS=_ArrayBinarySearch($avArray,"2008/01/03")
If $indBS<>-1 Then
     If $indBS>0 Then
          For $v=$indBS-1 To 0 Step -1
               If $avArray[$v]=$avArray[$indBS] Then
                    $iStart=$v
               Else
                    $iStart=$indBS
                    ExitLoop
            EndIf
          Next
     Else
          $iStart=$indBS
     EndIf
     If $indBS<UBound($avArray)-1 Then
          For $v=$indBS+1 To UBound($avArray)-1
               If $avArray[$v]=$avArray[$indBS] Then
                    $iEnd=$v
               Else
                    $iEnd=$indBS
                    ExitLoop
               EndIf
          Next
     Else
          $iEnd=$indBS
     EndIf
     For $v=$iStart To $iEnd
          MsgBox(0,"Date",$v&"<Index Date>"&$avArray[$v])
     Next
EndIf

[Edited: added ExitLoop, $iEnd & $iStart =$indBS and two Else statements > Thanks to cageman]

Question about forum :) How can I insert "Tab" in autoit code?

Edited by Eugenii

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

You still have inefficient code. If

$avArray[$v]<>$avArray[$indBS] you should step out of the for loop, because there is nothing to update. Now you walk over every element.

Another note. I think you should set istart and iend to

indBS if its > 0

Edited by cageman

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

Thanks again! You saved a lot of my time from debugging! I made all 2 corrections.

Edited by Eugenii

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

Still something could go wrong i think.

$iStart=$indBS should not be in that else statement, but before the for loop. Same holds for the end value.

Right now i think if you have 3 times a date and the middle one is found by binary search.

start = end = index of middle one instead of start = index of middle one - 1 and end = index of middle one + 1

#include <Array.au3>
#include <Date.au3>
#include <String.au3>

Local $avArray[21]=["2007/09/30", _ ;0
"2007/09/30", _ ;1
"2007/10/01", _ ;2
"2007/10/05", _ ;3
"2007/10/05", _ ;4
"2008/01/03", _ ;5
"2008/01/03", _ ;6
"2008/01/03", _ ;7
"2008/01/03", _ ;8
"2008/01/03", _ ;9
"2008/01/03", _ ;10
"2008/01/03", _ ;11
"2008/04/27", _ ;12
"2008/04/27", _ ;13
"2008/04/27", _ ;14
"2008/11/11", _ ;15
"2008/11/30", _ ;16
"2008/11/30", _ ;17
"2008/11/30", _ ;18
"2009/03/17", _ ;19
"2009/03/17"] ;20
_ArraySort($avArray)

$iStart=0
$iEnd=0
$indBS=0
$indBS=_ArrayBinarySearch($avArray,"2008/01/03")
If $indBS<>-1 Then
$iStart=$indBS
$iEnd=$indBS
     If $indBS>1 Then
         For $v=$indBS-1 To 1 Step -1
             If $avArray[$v]=$avArray[$indBS] Then
                 $iStart=$v
             Else
                 ExitLoop
            EndIf
         Next
     EndIf

     If $indBS<UBound($avArray)-1 Then
         For $v=$indBS+1 To UBound($avArray)-1
             If $avArray[$v]=$avArray[$indBS] Then
                 $iEnd=$v
             Else
                 ExitLoop
             EndIf
         Next
     EndIf

     For $v=$iStart To $iEnd
         MsgBox(0,"Date",$v&"<Index Date>"&$avArray[$v])
     Next
EndIf
Edited by cageman

Share this post


Link to post
Share on other sites

You are right once again!

Now I will try to compare _ArrayAdd/Delete function speed with manual value assignment for each element of an array (without call ReDim every time).

Share this post


Link to post
Share on other sites

_ArrayDelete/Add will definitely slow down your script because it calls ReDim every time.


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

water,

Thanks, you are right too! Simple code shows next difference: 0.027 against 19.4 seconds.

#include <Array.au3>

$timer=TimerInit()
Dim $array[5000]
$elCount=0
For $a=$elCount To UBound($array,1)-1
     $array[$a]=Random(0,100,1)
     $elCount+=1
Next
For $a=$elCount-1 To 0 Step -1
     $array[$a]=""
     $elCount-=1
Next
$t1=StringFormat("%.4f",TimerDiff($timer)/1000)

$timer=TimerInit()
Dim $array2[1]
For $a=1 To 5000
     _ArrayAdd($array2,Random(0,100,1))
Next
For $a=5000 To 1 Step -1
     _ArrayDelete($array2,$a)
Next
$t2=StringFormat("%.4f",TimerDiff($timer)/1000)

MsgBox(0,"","Manual "&$t1&"-"&$elCount&" Auto "&$t2&"-"&UBound($array2,1)-1)

2 questions are closed, 2 left.

Edited by Eugenii

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0