Jump to content

Positions of searchstring in a string


Recommended Posts

Hi,

I would like to cycle through all positions of a searchstring in a string.

Example:
111AB11111111AB11AB111111AB11

I would like to have all positions of the searchstring "AB". How can I do that with AutoIt? I can't find a String function for that.

 

Regards
Dolphins

Link to comment
Share on other sites

... a simple example

#include <array.au3> ; used to see result

Local $sMyString = "111AB11111111AB11AB111111AB11"
Local $sMySearch = "AB"

Local $aMyPositions = _StringFindAll($sMyString, $sMySearch)

_ArrayDisplay($aMyPositions, "Positions")

Func _StringFindAll($String, $sSearch, $iCasesense = 0)
    StringReplace($String, $sSearch, $sSearch) ; count how many occurrences (if any)
    Local $iOccurrences = @extended ; the number of replacements is stored in the @extended macro
    If $iOccurrences Then
        Local $aPositions[$iOccurrences] ; make room for results
        For $i = 1 To $iOccurrences
            $aPositions[$i - 1] = StringInStr($String, $sSearch, $iCasesense, $i)
        Next
        Return SetError(0, $iOccurrences, $aPositions)
    Else
        Return SetError(True)
    EndIf
EndFunc   ;==>_StringFindAll

 

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

a dirty example:

local $str = "111AB11111111AB11AB111111AB11" , $i = 0 , $pos = ""

Do
$i += 1
$pos &= StringInStr($str , "AB" , 1 , $i) & ","
Until stringright($pos , 3) = ",0,"

msgbox(0 , '' , stringtrimright($pos , 3))

 

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Link to comment
Share on other sites

@dolphins
Another example with SRE, even if the @iamtheky one is more beautiful ^_^

#include <StringConstants.au3>

Global $strString = "111AB11111111AB11AB111111AB11"

MsgBox($MB_ICONINFORMATION, "", _GetStringPositions($strString, "AB"))


Func _GetStringPositions($strString, $strSubstring)

    Local $intOffset, _
          $strReturn

    While 1

        StringRegExp($strString, $strSubstring, $STR_REGEXPARRAYMATCH, $intOffset)
        If @error Then ExitLoop
        $intOffset = @extended

        $strReturn &= ($intOffset - StringLen($strSubstring)) & ","

    WEnd

    Return StringLeft($strReturn, StringLen($strReturn) - 1)

EndFunc

 

Click here to see my signature:

Spoiler

ALWAYS GOOD TO READ:

 

Link to comment
Share on other sites

... we can still save a few bits  :whistle:

Local $str = '111AB11111111AB11AB111111AB11', $key = "AB", $r

For $i = 1 To StringSplit($str, $key, 1)[0] - 1
    $r &= StringInStr($str, $key, 1, $i) & ','
Next

MsgBox(0, '', StringTrimRight($r, 1))

 

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

theory time!!!

would simple counting ops be quicker in the loop than stringinstr ops? something like:

#include<array.au3>

Local $aStr = stringsplit('111AB11111111AB11AB111111AB11' , "AB" , 3) , $x = 1
_ArrayPop($aStr)

For $i = 0 To ubound($aStr) - 1
    $x += stringlen($aStr[$i])
    $aStr[$i] = $x
    $x+=2  ; length of $sMatch
Next


_ArrayDisplay($aStr)

 

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Link to comment
Share on other sites

20 hours ago, iamtheky said:

theory time!!!

would simple counting ops be quicker in the loop than stringinstr ops?

Hi @iamtheky,

actually it looks like that counting ops be quicker in the loop than stringinstr op

here I've modified my previous listing trying to speed up StringInString by limiting the range of the search for each loop,  nonetheless, even if quite improved, StringInString remains slower

Local $String = '111AB11111111AB11AB111111AB11', $key = "AB"

    Local $r, $x = StringLen($String)
    For $i = 1 To StringSplit($String, $key, 1)[0] - 1
        $x = StringInStr($String, $key, 1, -1, $x)
        $r = ',' & $x & $r
    Next
    MsgBox(0, 'result', StringTrimLeft($r, 1))

following is a list of all attempts in this thread to compare execution speeds for each with a final ranking in the _ArrayDisplay

#include<array.au3>

Global $String = '111AB11111111AB11AB111111AB11', $key = "AB"

; make a bigger string
For $i = 1 To 10
    $String &= $String
Next

Local $sCompetitors = "chimp1;iamtheky1;francescodimuro;mikell;chimp2;iamtheky2"

Local $aCompetitors = StringSplit($sCompetitors, ';'), $Timer
Local $aRanking[$aCompetitors[0]][2]
For $Rider = 0 To $aCompetitors[0] - 1
    $aRanking[$Rider][0] = $aCompetitors[$Rider + 1]
    $Timer = TimerInit()

    $Result = Call($aCompetitors[$Rider + 1])

    $aRanking[$Rider][1] = Int(TimerDiff($Timer))
    ConsoleWrite($aRanking[$Rider][0] & "'s result" & @CRLF)
    If IsArray($Result) Then
        ConsoleWrite(_ArrayToString($Result, ',') & @CRLF)
    Else
        ConsoleWrite($Result & @CRLF)
    EndIf
    ConsoleWrite("--------------------" & @CRLF)
Next

_ArraySort($aRanking, 0, 0, 0, 1)
_ArrayDisplay($aRanking, "final ranking")

Func iamtheky1()
    Local $pos, $i
    Do
        $i += 1
        $pos &= StringInStr($String, "AB", 1, $i) & ","
    Until StringRight($pos, 3) = ",0,"
    Return StringTrimRight($pos, 3)
EndFunc   ;==>iamtheky1


Func francescodimuro()

    Local $intOffset, _
            $strReturn

    While 1

        StringRegExp($String, $key, $STR_REGEXPARRAYMATCH, $intOffset)
        If @error Then ExitLoop
        $intOffset = @extended

        $strReturn &= ($intOffset - StringLen($key)) & ","

    WEnd

    Return StringLeft($strReturn, StringLen($strReturn) - 1)

EndFunc   ;==>francescodimuro

Func mikell()
    Local $r = "", $x

    For $i = 1 To StringLen($String)
        $x = StringInStr($String, $key, 1, $i)
        $r &= $x ? $x & ',' : ""
    Next
    Return StringTrimRight($r, 1)
EndFunc   ;==>mikell

Func chimp1()
    Local $r

    For $i = 1 To StringSplit($String, $key, 1)[0] - 1
        $r &= StringInStr($String, $key, 1, $i) & ','
    Next
    Return StringTrimRight($r, 1)
EndFunc   ;==>chimp1

Func chimp2()
    Local $r, $x = StringLen($String)
    For $i = 1 To StringSplit($String, $key, 1)[0] - 1
        $x = StringInStr($String, $key, 1, -1, $x)
        $r = ',' & $x & $r
    Next
    $r = StringTrimLeft($r, 1)
    Return $r
EndFunc   ;==>chimp2

Func iamtheky2()
    Local $aStr = StringSplit($String, $key, 3), $x = 1
    _ArrayPop($aStr)

    For $i = 0 To UBound($aStr) - 1
        $x += StringLen($aStr[$i])
        $aStr[$i] = $x
        $x += 2 ; length of $sMatch
    Next
    Return $aStr
EndFunc   ;==>iamtheky2

 

Edited by Chimp

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

3 hours ago, Chimp said:

actually it looks like that counting ops be quicker in the loop than stringinstr op

I don't agree  :)

I didn't know that it was matter of speed... I would have suggested this

Func mikell()
    Local $r = "", $len = Stringlen($key), $x = 1 - $len

    While 1
        $x = StringInStr($String, $key, 1, 1, $x + $len)
        If $x = 0 Then ExitLoop
        $r &= $x & ','
    Wend
    Return StringTrimRight($r, 1)
EndFunc   ;==>mikell

 

Link to comment
Share on other sites

a matter of speed sure, but not confined to this context.  I had not really ever considered these things beyond regex -vs- non-regex, now I kind of want to order the string* functions from fastest --> slowest.

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Link to comment
Share on other sites

16 hours ago, mikell said:

I didn't know that it was matter of speed... I would have suggested this

ah, damned Soulful cat ....  (I'm kidding of course ... it's a funny topic:muttley: )
however, I am sorry to disagree, but based on my tests your solution, even if close, is slower than that of @iamtheky,
or rather, by performing the test several times the results change slightly from time to time, but iamtheky's script is almost always the fastest. 

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

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