Jump to content

Recommended Posts

Posted (edited)

This is a little UDF i kind of got inspiration from that 'StringInChar' topic. This one takes 2 strings, the search string and a sub string, and it returns an array, per convention element 0 of the array contains the number of elements, (or occurances)and each of the other elements contains a position...

Func StringSubCount($ack, $arg);$ack and arg are source and sub string to search for
    $counter = 0
    Dim $blah[1]
        for $i = 1 to StringLen($ack)
        if StringMid($ack,$i,StringLen($arg)) = $arg then 
            $counter = $counter + 1
            _ArrayAdd($blah,$i)
            $blah[0] = $counter
        EndIf
    Next
        Return $blah
EndFunc

to see this in action, i used this code while writing it to check output.

#include <StringSubCount.au3>
$foo = "this is a test of how well this UDF counts the number of occurances of a sub string in a given string"
$bar = "this"
dim $blah[StringLen($foo)]
$blah = StringSubCount($foo,$bar)
_ArrayDisplay($blah,"test")

***edit***

not sure if this is similar to any others already created, if it is i'm sorry, i just kind of did it then decided to post it.... i totally forgot to check if there was something similar out there...

Edited by cameronsdad
Posted (edited)

Looks good, but I continue to beg people not to use _ArrayAdd inside a loop ...

And just for completeness, I'll throw in a CaseSense option.

And just to be anal, I will use sensical variable names :)

Func StringSubCount($String, $Sub, $CaseSense = 0)
    Local $i, $sl = StringLen($String), $ssl=StringLen($Sub), $Results[$sl+1]
    for $i = 1 to $sl
        if (Not $CaseSense And StringMid($String,$i,$ssl) = $Sub) Or ($CaseSense And StringMid($String,$i,$ssl) == $Sub) then
            $Results[0] += 1
            $Results[$Results[0]] = $i
        EndIf
    Next
    ReDim $Results[$Results[0]+1]
    Return $Results
EndFunc
Edited by blindwig
Posted

Looks good, but I continue to beg people not to use _ArrayAdd inside a loop ...

And just for completeness, I'll throw in a CaseSense option.

And just to be anal, I will use sensical variable names :)

Func StringSubCount($String, $Sub, $CaseSense = 0)
    Local $i, $sl = StringLen($String), $ssl=StringLen($Sub), $Results[$sl+1]
    for $i = 1 to $sl
        if (Not $CaseSense And StringMid($String,$i,$ssl) = $Sub) Or ($CaseSense And StringMid($String,$i,$ssl) == $Sub) then
            $Results[0] += 1
            $Results[$Results[0]] = $i
        EndIf
    Next
    ReDim $Results[$Results[0]+1]
    Return $Results
EndFunc

<{POST_SNAPBACK}>

i like the way you handled the array, and the variable name were a good touch, but case sense? are you mad?!

I'm just kidding. sorry i didn't even think about case when i was making it because the things i would use it for are typically all generated in all uppercase, and i typically type in all lowercase, so i just took the easy way out...

Posted

I'm just kidding. sorry i didn't even think about case when i was making it because the things i would use it for are typically all generated in all uppercase, and i typically type in all lowercase, so i just took the easy way out...

<{POST_SNAPBACK}>

Yeah, I hardly ever need case sense, but I write it in all my string functions because on the day when I do need it, I don't want to have to go back and rewrite all my functions. :)
Posted

Looks good, but I continue to beg people not to use _ArrayAdd inside a loop ...

<{POST_SNAPBACK}>

Just wondering, why don't you like using _ArrayAdd() in a loop?

qq

Posted (edited)

_ArrayAdd() uses ReDim, which I imagine would internally involve creating a new array in memory that's larger, copying the values one-by-one to the new array and deleting the old array.

All of this takes time and so a loop using _ArrayAdd() would most likely be considerably slower than a loop that doesn't. In most cases it would be possible to determine how many extra elements are needed and then resize the array in one go before using a For..Next loop to populate it with data.

Edited by LxP
Posted

Just wondering, why don't you like using _ArrayAdd() in a loop?

<{POST_SNAPBACK}>

Look at the code for _ArrayAdd() - it ReDims the array everytime you add an element. That's so slow and memory intensive - why not just make the array big enough to hold all the elements you need? Or make it too big (just in case) and then trim it when you're done?

_ArrayAdd() ReDims the array by 1 element at a time. My own version (called _Array1Add() ) doubles the array each time, so it makes my loops exponentially faster than using the stock _ArrayAdd() functions.

Posted

Thanks both for clearly up. I didn't bother to look at the code for _ArrayAdd() lol. I think now I have to go back over some old scripts and fix this, where speed is a comfort for the user.

qq

Posted

Hey, that's alot like my _StringFindOccurances function:

Func _StringFindOccurances($sStr1, $sStr2)
    For $i = 1 to StringLen($sStr1)
        If not StringInStr($sStr1, $sStr2, 1, $i) Then ExitLoop
    Next
    Return $i - 1
EndFunc

...only better. Great job! :)

Posted

Hey, that's alot like my _StringFindOccurances function:

Func _StringFindOccurances($sStr1, $sStr2)
    For $i = 1 to StringLen($sStr1)
        If not StringInStr($sStr1, $sStr2, 1, $i) Then ExitLoop
    Next
    Return $i - 1
EndFunc

...only better. Great job!  :)

<{POST_SNAPBACK}>

It's a good function, I've got one something like that as well.

But it looks like the OP was looking for a list of the occurances, not just the total count, which is why he's using an array.

Posted

It's a good function, I've got one something like that as well.

But it looks like the OP was looking for a list of the occurances, not just the total count, which is why he's using an array.

<{POST_SNAPBACK}>

one thing that i made this for was for a file parse, by using it to check the delimiter, can instantly tell how many columns are needed to handle the info, and don't have to worry about ever trying to assign a value that doesn't exist...

like on the timeclock program, it reads in the values to populate 8 labels from a text file, but only labels that had non default values at last unload would get new data... so rather than trying to assign non existent data to a variable, etc, can have it see that i have 5 delimiters, so only the first 6 get values... and i can use the array to clean up the stringMid that grabs the actual value...

$value = StringMid($String,$blah[1] + 1, $blah[2] - ($blah[1] + 1))

looks a little nicer than

$value = StringMid($String,StringInStr($String,",") + 1,StringInString($String,",",2) - (StringInStr($String,",") + 1))
Posted

one thing that i made this for was for a file parse, by using it to check the delimiter, can instantly tell how many columns are needed to handle the info, and don't have to worry about ever trying to assign a value that doesn't exist...

like on the timeclock program, it reads in the values to populate 8 labels from a text file, but only labels that had non default values at last unload would get new data... so rather than trying to assign non existent data to a variable, etc, can have it see that i have 5 delimiters, so only the first 6 get values... and i can use the array to clean up the stringMid that grabs the actual value...

$value = StringMid($String,$blah[1] + 1, $blah[2] - ($blah[1] + 1))

looks a little nicer than

$value = StringMid($String,StringInStr($String,",") + 1,StringInString($String,",",2) - (StringInStr($String,",") + 1))

<{POST_SNAPBACK}>

Are you aware of the StringSplit() function? I think it will do what you're wanting to do. It takes a string, and splits it up into an array of substrings based on a specified delimter string (which is either a list of delimiters, or a big single delimiter). Check the helpfile for details.

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
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...