Link to home
Start Free TrialLog in
Avatar of jozne
jozne

asked on

how to make faster code - my code has too many FOR sentences(?)

ok here is my code. I need better option for doing this thing, since
this way is TOO SLOW for my purposes and I can't figure out any other / faster way
to do it. so if someone could help me with this it would be GREAT! :)

and, for qui = 1 to 1000 is there, because this code that I have there, is going
to run OVER 1000 times before finish, so I added it to see the delay in 1000 times. If someone could squeez the time that code runs to even ½, it would be big help. I guess that those FOR
sentences makes the code run longer and if there would be a way to do this without running so many FOR 's the speed would drop.. dunno :o

so here's the code (coordinates are in memory string, example -> x,y-x,y-x,y where the "-" is separator)

sub do_things()
timestart = Time
memory = "5,2-5,3-5,4-5,5-5,6-5,7-5,8-5,9-5,10-5,11-5,12"
For qui = 1 To 1000
char_start = 1
            pituus_memory = Len(memory)
            For q = 1 To pituus_memory
                If Mid(memory, q, 1) = "," Then coord_num = coord_num + 1
            Next
            For coordinates = 1 To coord_num
                char_count = 0
                For pepe = char_start To pituus_memory
                    If Mid(memory, pepe, 1) <> "-" Then char_count = char_count + 1
                    If Mid(memory, pepe, 1) = "-" Then Exit For
                Next
                If "5,123" = Mid(memory, char_start, char_count) Then Exit For
                char_start = char_start + char_count + 1
            Next
Next
            timeend = Time
            MsgBox timestart & " -- " & timeend
end sub

if you have questions, ask and I'll give more details. so this is a part of my bigger code where I have about ~6000 memory strings to check, so don't mind the for qui = 1 to 1000
Avatar of calin131
calin131
Flag of Canada image

i think i got the ideea about your code if i am wrong correct me:
you are trying to find in a string memory the characters "5,123" in between 2 "-" and if you find it then you increase qui if not you continue till the end of the string and if still not found then increase qui

the code i see for that should be this way a bit faster:
dim i as integer
dim found as boolean
dim end_of_search as integer 'this is used to store the position of the last char read from the string befor it reads "-"
For qui =1 to 1000
       char_start=1
       pituus_memory=Len(memory)
       end_of_search=0
       found=False
       Do Until (i=pituus_memory) OR (found=True)
                if(Mid(memory,i,1)="-" then
                         end_of_search=i
                         if Mid(memory,char_start,pituus_memory-end_of_search) ="5,123" then
                                       found=True

                          endif
                           char_start=end_of_search+1
                 endif
                 i=i+1

       loop


Next
try this and let me know how it goes
thanks
sorry i forgot this after the Next
timeend = Time
            MsgBox timestart & " -- " & timeend
end sub
You can save lots of time by using the Split function instead of this loop:

For q = 1 To pituus_memory
    If Mid(memory, q, 1) = "," Then coord_num = coord_num + 1
Next

'====================================================

Sub do_things()

    Dim TimeStart As Date, TimeEnd As Date
    Dim Memory As String
    Dim qui As Long
    Dim char_start As Long
    Dim pituus_memory As Long
    Dim q As Long
    Dim coord_num As Long
    Dim coordinates As Long
    Dim char_count As Long
    Dim pepe As Long
    Dim splitarray() As String

    TimeStart = Time
   
    Memory = "5,2-5,3-5,4-5,5-5,6-5,7-5,8-5,9-5,10-5,11-5,12"
   
    For qui = 1 To 1000
       
''        pituus_memory = Len(Memory)
''        For q = 1 To pituus_memory
''            If Mid(Memory, q, 1) = "," Then coord_num = coord_num + 1
''        Next

        splitarray = Split(Memory, ",")
        coord_num = UBound(splitarray)
       
        char_start = 1
        For coordinates = 1 To coord_num
            char_count = 0
            For pepe = char_start To Len(Memory)
                If Mid(Memory, pepe, 1) <> "-" Then char_count = char_count + 1
                If Mid(Memory, pepe, 1) = "-" Then Exit For
            Next
            If "5,123" = Mid(Memory, char_start, char_count) Then Exit For
            char_start = char_start + char_count + 1
        Next
    Next
    TimeEnd = Time
   
    Debug.Print qui
    MsgBox Format(TimeEnd - TimeStart, "hh:nn:ss")
   
End Sub

Avatar of bc10
bc10

Always tell your Next statements what is next i.e for i=1 to 10 next i.  This gives a slight improvment in execution time.
ASKER CERTIFIED SOLUTION
Avatar of PaulHews
PaulHews
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Erick's code 0.598 s
My Code     0.012 s

These are for 10000 iterations of the main loop, so both represent significant optimization over the original, however, mine is many times faster than Erick's.  Your performance may vary depending on the real life data you have, but my approach will be significantly faster than a looping comparison.

Using "Next i" instead of "Next" if it has any effect at all, which I'm not convinced, is not enough of an optimization to even mention.  I've done a fair amount of testing, and have yet to see any difference.
Are we trying to determine if the coordinate "5,123" exists in the string, or are we trying to determine where in the string "5,123" belongs?
in my code is both if you retrieve the value of :
dim start as integer
dim fin as integer

start=char_start
fin=pituus_memory-end_of_search

these 2 lines myst be added in the if where the found=true
Avatar of jozne

ASKER

it is to check if the "5,123" string is in the main Memory string.
Ok...

Sub do_things3()

    Dim TimeStart As Single, TimeEnd As Single
    Dim Memory As String
    Dim sTmpMem As String
    Dim sSearch As String
    Dim qui As Long
    Dim pos As Long
 

    TimeStart = Timer
   
    'the main string
    Memory = "5,2-5,3-5,4-5,5-5,6-5,7-5,8-5,9-5,10-5,11-5,12"
    'what we are looking for
    sSearch = "5,123"
   
    sSearch = "-" & sSearch & "-"
   
    For qui = 1 To 10000
       
        sTmpMem = "-" & Memory & "-"
        pos = InStr(1, sTmpMem, sSearch)
        'If the string exists, pos will point to the character position
        'If the string does not exist, then pos will be 0
       
    Next
   
    TimeEnd = Timer

    MsgBox Format(TimeEnd - TimeStart, "0.000")
   
End Sub
Erick, that's the same as my code, except it doesn't check if the coordinates exist in the first or last position of the string.
Yes it does...

sTmpMem = "-" & Memory & "-"
Ah, so it does.  :)

You are correct Paul, it is the same idea.  I looked at the question again because of your idea to search for  "-5,123-"  I did not know exactly what the code was supposed to do.

jzone - PaulHews gets credit for the algorithm.

One possible bug:
               'this evaluates true
                ElseIf StrComp(Right$(Memory, 6), "-5,123") Then 'test end
                    lngPos = Len(Memory) - 4
                End If
Avatar of jozne

ASKER

what about
check = InStr(1, Memory, "5,123")   and if check > 0 then found?
since, I need it only to check if it is in there, nothing else...
That would also match "25,1234"
Avatar of jozne

ASKER

ok thanks :)

btw. is there any faster way than For...Next to do this

path(1) = "1"
path(2) = "2"
path(3) = "3"
path(4) = "4"

for i = 1 to 5 'should push all path(i) to 1 up
     if path(0) = "" then path(0) = path(1): helper = i
     if path(0) <> "" then path(helper) = path(i): helper = i
next i
'resulting path(0) = 1, path(1) = 2, path(2) = 3, path(3) = 4

And thanks to you paul, I'll be closing the question soon :)
Good point Erick, should be:

ElseIf StrComp(Right$(Memory, 6), "-5,123") = 0 Then 'test end
    lngPos = Len(Memory) - 4
End If

Although since we just need to test for existence, the version you provided would be fastest.

>btw. is there any faster way than For...Next to do this
No, you will have to touch each member of the array, and the fastest way would be a for ... next loop.  If your array is small that won't be a problem.

Something like this?

For i = Lbound(path) to Ubound(path)
   path(i) = Cint(path(i)) + 1
Next i
jozne, thanks for the points.  :)

I hope you got what you needed here.

Erick37 I think some points should have gone your way on this answer, which was a collaboration:
https://www.experts-exchange.com/questions/21350278/For-Erick37.html