Jump to content

Another String UDF


seandisanti
 Share

Recommended Posts

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
Link to comment
Share on other sites

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
Link to comment
Share on other sites

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...

Link to comment
Share on other sites

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. :)
Link to comment
Share on other sites

_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
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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! :)

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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))
Link to comment
Share on other sites

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.
Link to comment
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
 Share

  • Recently Browsing   0 members

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