NotStr() : Switch between multiple states

Post your working scripts, libraries and tools
User avatar
SKAN
Posts: 861
Joined: 29 Sep 2013, 16:58

Re: NotStr() : Switch between multiple states

Post by SKAN » 24 Apr 2020, 08:52

SpeedMaster wrote:
24 Apr 2020, 08:13
Thanks for this usefull function :D :thumbup:

Is it also possible to add an option for the direction ? :think:

NotStr(S:="", Z:="", D:="|", dir:="1")

dir = 1 ; cycle forward
dir = -1 ; cycle backward
dir = 0 ; reset/restore starting pos
I had thought of that. Too costly (codewise) to implement.
Did you try my GUI demo? I just reverse the string instead of trying to read reverse.
SpeedMaster wrote:
24 Apr 2020, 08:13
I think a function without it's description is almost a dead function. :(
I recomand to put the help and usage right above the function.
I disagree. A function with usage examples is not a dead function.. at least not to those who are inquisitive.
How hard is to try a 2 line examples posted with the title: Functionality explained with examples:?

Code: Select all

[u]good example [/u]: ST library  [c]https://www.autohotkey.com/boards/viewtopic.php?f=6&t=53[/c]
ST library is missing some of your functions so I added them into my personal ST library. ( :shh:  I hope you don't mind. :shifty:)
Why not? Put them to good use my friend :)
User avatar
SpeedMaster
Posts: 409
Joined: 12 Nov 2016, 16:09

Re: NotStr() : Switch between multiple states

Post by SpeedMaster » 24 Apr 2020, 12:22

SKAN wrote:
24 Apr 2020, 08:52
Did you try my GUI demo? I just reverse the string instead of trying to read reverse.
Very good idea. 8-) I will try to find a field reverser function or maybe someone else can make one.
SKAN wrote:
24 Apr 2020, 08:52
How hard is to try a 2 line examples posted with the title: Functionality explained with examples:?
I only talk about my personal experience when I find a function that interests me I copy it into my main script or in a personal library. The problem is that it is difficult to remember a few months or years later, who made the function and where is the topic with the descriptions for each parameter. Of course now I don't make this mistake anymore and try to make a short description and usage before pasting it somewhere else but doing this takes time and it's always welcome when the function already contains all this.

of course I can always try to be inquisitive :geek:

here is a function: :wtf: :eh: :headwall:
function
...
But I'd rather avoid this laborious investigation work. :yawn:
here is the same function: 8-) :beer:
function
SKAN wrote:
24 Apr 2020, 08:52
Why not? Put them to good use my friend
:superhappy: Thanks
User avatar
SpeedMaster
Posts: 409
Joined: 12 Nov 2016, 16:09

Re: NotStr() : Switch between multiple states

Post by SpeedMaster » 26 Apr 2020, 14:01

SpeedMaster wrote:
24 Apr 2020, 08:13
Is it also possible to add an option for the direction ?
SKAN wrote:
24 Apr 2020, 08:52
I had thought of that. Too costly (codewise) to implement.
You're right, but it's worth it. :roll:
I managed to make one that can go backwards. 8-)
I also added a few extra options like the possiblity to disable wrapping around the end ...

CycleStr(Value, unique fields, [ Delimiter, direction, wrapping around ])

here is the function:

Code: Select all

/*
CycleStr v.1.2 by Speedmaster
  function to cycles to the next or previous value in a set of values ex. "A|B|C|D"

  CycleStr(s:="", Z:="", D:="|", dir:=1, cycle:=true)
  S = a value in the set Z.
  Z = set of values, a string of delimited values. for ex. "red|green|blue"
      you can also auto build a range for numbers syntax is "R:Min:Max:PaddingZeros" for ex. "R:25:99:3"  ==> 025|026...099
  D = Delimiters can be either a single string or an array of strings. (default is "|")
  dir = 0 go to home, 1 cycle forward, -1 cycle backward, 2 go to end
  Cycle = false/true allow wrapping around the end.

examples:
    CycleStr("B", "A|B|C") returns "C" next value
    CycleStr("B", "A|B|C",,-1) returns "A" previous value
    CycleStr("C", "A|B|C") returns "A" (wrap around to right)
    CycleStr("A", "A|B|C",,-1) returns "C" (wrap around to left)
    CycleStr("C", "A|B|C",,1,false) returns "C" (wrapping around disabled)
    CycleStr("33", "R:55:100:3") returns "034" (build a range of values from 055 to 100)  "055|056...100"
    CycleStr("A", "A B/C",[" ", "/"]) returns "B" (mixed delimiters are supported in an array of strings)
    CycleStr("r", "abcdefghijklmnopqrstuv","") returns "s" (if there is no delimiter values are split by chars)
;---------------------------------
;script example :
item:="cherry"
right::tooltip, % item:=CycleStr(item,"Apple|Banana|Cherry|Durian|Fig",,1) ; start at "cherry" show next value and wrap around at end
left::tooltip, % item:=CycleStr(item,"Apple|Banana|Cherry|Durian|Fig",,-1,false) ; start at "cherry" show previous value and stop at first value
home::tooltip, % item:=CycleStr(item, "Apple|Banana|Cherry|Durian|Fig",,0) ; jump to home of list
end::tooltip, % item:=CycleStr(item, "Apple|Banana|Cherry|Durian|Fig",,2) ; jump to end of list
*/
CycleStr(S:="", Z:="", D:="|", dir:=1, cycle:=true) {
  if (regexmatch(z, "i)R:? ?(-?\d+):(-?\d+):?(\d\d?)?", num)) {
    --num1
    while (num1++ < num2) {
        if (num3!="")
            numrange .= Format("{:0" num3 "}", num1) (D?D:D:="|")
       else
            numrange .= num1 (D?D:D:="|")
    }
    z:=rtrim(numrange, (D?D:D:="|"))
  }
 oz:=strsplit(z, d), ozb:=[]
 for k, v in oz
   ozb[v,1]:=oz[(K+1)<=oz.length()?(k+1):1], ozb[v,2]:=oz[(k-1)>0?(k-1):oz.length()]
 if (dir=0)
  return ozb[oz[oz.length()],1] ; start of list dir=0
 if (dir=2) 
  return ozb[oz.1,2] ; end of list dir=2
 if (!cycle && (dir>0) && (s=oz[oz.length()]))
    return s
 if (!cycle && (dir=-1) && (s=oz[1]) && oz.length()) ;&& msgbox("")  ; cycle disabled
    return s
return, ozb[ozb[s].length()?s:(oz[(dir>0)?(oz.length()):1])][(dir>0)?1:2]   
}
Demo script for strings:

Code: Select all

#SingleInstance force

gui, font, s12
wraparound:=true
fruits:="Apple|Banana|Cherry|Durian|Fig|Grape|Kumquat|Lychee|Mango|Nectarine|Orange|Papaya|Quince|Yuzu"
gui, add, text, w800 , % "CycleStr() demo`n`n" fruits
gui, add, text, , Press cursors to show values `n(up=home,   down=end,   right=next,   left=previous)
gui, add, text, x80 center border w200 vtxt, 
gui, add, checkbox, checked X+10 vwraparound gckb, wrap around
gui, show, 

left::
item:=CycleStr(item, fruits,,-1,wraparound)
goto print
return

right::
item:=CycleStr(item, fruits,,1,wraparound)
goto print
return

up::
item:=CycleStr(item, fruits,,0)
goto print
return

down::
item:=CycleStr(item, fruits,,2)
goto print
return

ckb:
gui, submit, nohide
return

print:
guicontrol,,txt, % item
return

esc::
guiclose:
exitapp
Demo script for a range of numbers

Code: Select all

#SingleInstance force

gui, font, s12
wraparound:=true
values:="CycleStr( "" R:Min:Max:Padding "" )     ex. num:=cyclestr(num, "" r:1:1000:5 "" )"
gui, add, text, w550 , % "CycleStr() demo cycling numbers with zero padding`n`n"  . values
gui, add, text, , Press cursors to show values `n(up=home,   down=end,   right=next,   left=previous)
gui, add, text, x80 center border w200 vtxt, 
gui, add, checkbox, checked X+10 vwraparound gckb, wrap around
gui, show, 

left::
item:=CycleStr(item, "r0:1000:5",,-1,wraparound)
goto print
return

right::
item:=CycleStr(item, "r0:1000:5",,1,wraparound)
goto print
return

up::
item:=CycleStr(item, "r0:1000:5",,0)
goto print
return

down::
item:=CycleStr(item, "r0:1000:5",,2)
goto print
return

ckb:
gui, submit, nohide
return

print:
guicontrol,,txt, % item
return

esc::
guiclose:
exitapp

Cheers
Last edited by SpeedMaster on 15 May 2020, 06:02, edited 4 times in total.
User avatar
SKAN
Posts: 861
Joined: 29 Sep 2013, 16:58

Re: NotStr() : Switch between multiple states

Post by SKAN » 26 Apr 2020, 17:12

SpeedMaster wrote:
26 Apr 2020, 14:01
SpeedMaster wrote:
24 Apr 2020, 08:13
Is it also possible to add an option for the direction ?
SKAN wrote:
24 Apr 2020, 08:52
I had thought of that. Too costly (codewise) to implement.
You're right, but it's worth it. :roll:
I managed to make one that can go backwards. 8-)
I also added a few extra options like the possiblity to disable wrapping around the end ...
Nice demo :bravo: Works great!

One more time I'm going to say this. NotStr() is more about logic than cycling a series of string.

Code: Select all

NotStr(A_IsUnicode,"1|2")
The above snippet is already super slower than the ternary equivalent Not A_IsUnicode ? 1 : 2
Why would I want to read backward and make it even more slower?
User avatar
SKAN
Posts: 861
Joined: 29 Sep 2013, 16:58

Code updated: NotStr() v0.6a

Post by SKAN » 26 Apr 2020, 17:33

Code updated: NotStr() v0.6a.

Code enhanced to handle a couple of exceptions
NotStr("True","True") was returning True. It will correctly result in a blank.
NotStr("","") was returning blank. Now it will be 1.
Note that the basic rule of NotStr() is to Not return the source Str (Parameter 1)
User avatar
SpeedMaster
Posts: 409
Joined: 12 Nov 2016, 16:09

Re: NotStr() : Switch between multiple states

Post by SpeedMaster » 27 Apr 2020, 03:05

SKAN wrote:
26 Apr 2020, 17:12
The above snippet is already super slower than the ternary equivalent Not A_IsUnicode ? 1 : 2
I couldn't agree more. If you want to process a large amount of data and speed is important to you don't use these two functions CycleStr() & NotStr() or even better don't use AHK :!: (use machine code or another langage instead), but for a basic usage both functions are quite fast. :|
Speed should not be the only concern for a programmer flexibility is also important. :thumbup:
SpeedMaster wrote:
24 Apr 2020, 12:22
Did you try my GUI demo? I just reverse the string instead of trying to read reverse.
Why would I want to read backward and make it even more slower?
I try to read backwards precisely to save me the effort of manually reversing the fields. :|
:arrow: CycleStr() is more about cycling a series of string than logic.

cheers
Last edited by SpeedMaster on 27 Apr 2020, 07:59, edited 1 time in total.
User avatar
SKAN
Posts: 861
Joined: 29 Sep 2013, 16:58

Re: NotStr() : Switch between multiple states

Post by SKAN » 27 Apr 2020, 04:15

SpeedMaster wrote:Speed should not be the only concern for a programmer flexibility is also important. :thumbup:
You shouldn't decide for others. :P
SpeedMaster wrote: :arrow: CycleStr() is more about cycling a series of string than logic.
Glad we agree these functions are for different purposes. :)

I wonder what application you have in mind for CycleStr()
One use I can think of:
Say my list is a bunch of windows handles, I can do Alt-tab switching with NotStr()
With CycleStr(), I could additionally do Shift-Alt-tab which is definitely an advantage.

:)
User avatar
SKAN
Posts: 861
Joined: 29 Sep 2013, 16:58

Re: NotStr() : Switch between multiple states

Post by SKAN » 27 Apr 2020, 04:43

SpeedMaster wrote:You can still compare both functions in terms of flexibility and not only speed. :think:
What kind kind of comparison are you making. You are passing parameters that makes no sense to NotStr()
You may as well as do comparisons like CycleStr() vs InsStr() or CycleStr() vs SubStr() and claim they are not flexible.
It is better to stop comparisons here. It makes no sense to this topic.

I stopped writing "one script fits all" type code 14 years ago after some good advice from my friend @BoBo
User avatar
SpeedMaster
Posts: 409
Joined: 12 Nov 2016, 16:09

Re: NotStr() : Switch between multiple states

Post by SpeedMaster » 27 Apr 2020, 08:28

SKAN wrote:
27 Apr 2020, 04:15
You shouldn't decide for others.
I just gave my point of view, that's all. :silent: :roll:
SKAN wrote:
27 Apr 2020, 04:15
I wonder what application you have in mind for CycleStr()
One use I can think of:
Say my list is a bunch of windows handles, I can do Alt-tab switching with NotStr()
With CycleStr(), I could additionally do Shift-Alt-tab which is definitely an advantage.
Yes you get the point, switching forward and backward in a list is definitely an advantage :thumbup: (At least for me :mrgreen: ).
SKAN wrote:
27 Apr 2020, 04:43
What kind kind of comparison are you making. You are passing parameters that makes no sense to NotStr()
Yeah, that's usually what I do when I want to try something. I just give it a try and see wat happens. :)
SKAN wrote:
27 Apr 2020, 04:43
You may as well as do comparisons like CycleStr() vs InsStr() or CycleStr() vs SubStr() and claim they are not flexible.
It is better to stop comparisons here. It makes no sense to this topic.
My apologies, that kind of comparison is really not productive :geek: . I take it back. :facepalm:
SKAN wrote:
27 Apr 2020, 04:43
I stopped writing "one script fits all" type code 14 years ago after some good advice from my friend @BoBo
I don't think I put too many parameters in the CycleStr() function. I admit it's borderline, though. :think:
https://www.youtube.com/watch?v=-AQfQFcXac8
Have a nice day !
neogna2
Posts: 86
Joined: 15 Sep 2016, 15:44

Re: Code updated: NotStr() v0.6a

Post by neogna2 » 28 Apr 2020, 16:03

Nice to now have two functions! Thank you both. :thumbup:
SKAN wrote:
26 Apr 2020, 17:33
Code enhanced to handle a couple of exceptions
NotStr("True","True") was returning True. It will correctly result in a blank.
NotStr("","") was returning blank. Now it will be 1.
Note that the basic rule of NotStr() is to Not return the source Str (Parameter 1)
The example ("1", "1") is useful to highlight the difference between two similar yet distinct functions that can both have their uses.

NotStr("1", "1") returns "" which makes sense as per your basic rule.

CycleStr("1","1") returns "1" which makes sense if its (different) basic rule is to always return the next value from the second parameter set. In this edge case the set only has one item so the next value, after wrapping around, is the same as the first parameter input value.
User avatar
SKAN
Posts: 861
Joined: 29 Sep 2013, 16:58

NotStr()

Post by SKAN » 28 Apr 2020, 18:32

Here is my real world application. I use 3 edit controls and 5 buttons to form a command line for my C compiler.
Radio buttons occupy too much space and DropDownList controls are cumbersome to use. So I've implemented normal buttons for switching.
These command line switches range from single state to five states... on average three... So I don't have to click around much.

  • Image
neogna2 wrote:NotStr("1", "1") returns "" which makes sense as per your basic rule.
Yes. There are single state switches that needs to toggle to blank to be omitted from the command line,
User avatar
SpeedMaster
Posts: 409
Joined: 12 Nov 2016, 16:09

Re: NotStr() : Switch between multiple states

Post by SpeedMaster » 05 May 2020, 03:34

Hello,

Code updated: CycleStr() v1.1

New feature

[*] Added support for padding zeros to the numbers when creating a range.

:!: New syntax is "R:Min:Max:Padding" for ex. num:=CycleStr(num, "R:1:120:4") will build a range from 0001 to 0120
:!: Up to 99 zeros can be padded

See previous post above for code and demos.
https://www.autohotkey.com/boards/viewtopic.php?f=6&t=74948&start=20#p325137

Cheers
Last edited by SpeedMaster on 15 May 2020, 06:20, edited 1 time in total.
User avatar
SKAN
Posts: 861
Joined: 29 Sep 2013, 16:58

NotStr() - Updated

Post by SKAN » 10 May 2020, 21:02

Code updated: NotStr() v0.6b.

NotStr() v0.6a didn't work correctly when delimiter was multiple chars.
Now fixed.
burque505
Posts: 1447
Joined: 22 Jan 2017, 19:37

Re: NotStr() : Switch between multiple states

Post by burque505 » 11 May 2020, 07:51

@SKAN, thanks for the continued updates. 0.6b is working great on Win7 Pro 64-bit, AHK 1.1.32.00.

I really like the way you've formatted the ternary operators in the "readable" version of the script.

Regards,
burque505


(Just as an aside, for the GUI example, resizing the edit control as is coded as Alt+<Arrow>, but the label indicates Ctrl+<Arrow>. Scarcely worth mentioning.)
User avatar
SKAN
Posts: 861
Joined: 29 Sep 2013, 16:58

Re: NotStr() : Switch between multiple states

Post by SKAN » 11 May 2020, 08:35

burque505 wrote:Just as an aside, for the GUI example, resizing the edit control as is coded as Alt+<Arrow>, but the label indicates Ctrl+<Arrow>. Scarcely worth mentioning.
Oops. :oops:
Fixed code and screenshot.
Thank you. :thumbup: :)
User avatar
SpeedMaster
Posts: 409
Joined: 12 Nov 2016, 16:09

Re: NotStr() : Switch between multiple states

Post by SpeedMaster » 15 May 2020, 06:19

Hello,

Code updated: CycleStr() v1.2 ;)

New feature

[*] Minor bug fix: (when no starting value is set and going in backward direction the script was returning value Max-1 instead of Max as first value)

See previous post above for code and demos.
https://www.autohotkey.com/boards/viewtopic.php?f=6&t=74948&start=20#p325137

Cheers
burque505
Posts: 1447
Joined: 22 Jan 2017, 19:37

Re: NotStr() : Switch between multiple states

Post by burque505 » 15 May 2020, 08:05

Thanks, @SpeedMaster, works great.
Regards,
burque505
piddly
Posts: 6
Joined: 19 May 2020, 03:48

Re: NotStr() : Switch between multiple states

Post by piddly » 19 May 2020, 04:00

My first post, pl. forgive boo-boos. Following is my take. Returns 1st element if needle is blank. Last parameter case-sensitivity.

Code: Select all

 Test: h := "a|ba|b|ab|aa|bb", n := "bb"
         MsgBox % Next(h, n)
Function:

Code: Select all

 Next(h, n = "", s = "|", c = 1)
 { z := StrSplit(h, s)[1], h := s h s z s, p := InStr(h, s n s, c),  q := InStr(h, s,, p + StrLen(n) + 1), r := InStr(h, s,, q + 1)
  return n = "" ? z : one = 0 ? "" : SubStr(h, q + 1, r - q - 1)
 }
Edited by SKAN : Applied code tags.
piddly
Posts: 6
Joined: 19 May 2020, 03:48

Re: NotStr() : Switch between multiple states

Post by piddly » 19 May 2020, 04:19

Repost in proper format (I hope).

Code: Select all

; Test
h := "a|ba|b|ab|aa|bb", n := "bb"
MsgBox % Next(h, n)
; Function. h = haystack, n = needle, s = separator, c = case-sensitive
;  returns "" if n not found, 1st element if n blank, reverse order not implemented yet.
Next(h, n = "", s = "|", c = 1)
{ z := StrSplit(h, s)[1], h := s h s z s, p := InStr(h, s n s, c), q := InStr(h, s,, p + StrLen(n) + 1), r := InStr(h, s,, q + 1)
 return n = "" ? z : one = 0 ? "" : SubStr(h, q + 1, r - q - 1)
}
piddly
Posts: 6
Joined: 19 May 2020, 03:48

Re: NotStr() : Switch between multiple states

Post by piddly » 19 May 2020, 04:20

Thanks, SKAN.
Post Reply

Return to “Scripts and Functions”