if var in/contains comma-separated list/array

Discuss the future of the AutoHotkey language
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

if var in/contains comma-separated list/array

31 Jan 2018, 00:59

At the moment in AHK v1, we have:
if var contains Mon,Tue,Wed,Thu,Fri,Sat,Sun

In AHK v2, this would probably become:
if var contains ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"]
Which is far less convenient.
Such lists are inconvenient to type, although hotkeys to prepare the text are possible.

This would be made more bulky by script correctors that automatically separate parameters.
if var contains ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
(You might say 'don't use a corrector', but in general I've found that it's better to use one than not to use one, and that it's simpler to apply it to all arrays than to try to make exceptions.)

This would be less inconvenient to type, but still a bit bulky:
if var contains StrSplit("Mon,Tue,Wed,Thu,Fri,Sat,Sun", ",")

A workaround:
if var contains CSL("Mon,Tue,Wed,Thu,Fri,Sat,Sun")
if var contains PSL("Mon|Tue|Wed|Thu|Fri|Sat|Sun")
CSL/PSL aren't too bad, but using that every time?

An alternative. Something like this perhaps!?
if var containsCSL "Mon,Tue,Wed,Thu,Fri,Sat,Sun"

Some further alternatives.
if StrContains(var, "Mon,Tue,Wed,Thu,Fri,Sat,Sun", "D,")
if StrContains(var, "Mon|Tue|Wed|Thu|Fri|Sat|Sun", "D|")
if StrContainsCSL(var, "Mon,Tue,Wed,Thu,Fri,Sat,Sun")

Also, there's RegExMatch. But this has the drawbacks of: checking for characters that need escaping, having to use pipes, being slow.
if RegExMatch(var, "Mon|Tue|Wed|Thu|Fri|Sat|Sun")

Btw I would generally never use [] to define an array, I would always use something like CSL if available:
oArray := ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"]
oArray := CSL("Mon,Tue,Wed,Thu,Fri,Sat,Sun")
(Although for numbers, the [] syntax does remain useful.)
oArray := [1,2,3,4,5,6,7]

I believe that most people including myself: (a) see delimiter-separated strings as a bit old-fashioned cf. arrays, (b) see it as hard to justify interpreting a string as comma-delimited by default. However, the comma/pipe-separated list remains very useful.

I believe also that in AHK v1, and in AHK v2 alpha at the moment, arrays are almost never used as input parameters for functions, and so key issues, and the practical reality of their day-to-day use, haven't really been considered yet. Because it's new territory, and because it takes some time to work out how to develop a new syntax, I am concerned that it's the sort of thing where people might not quite get the syntax right and potentially end up saying: we need to fix this in AHK v3.

Thanks for reading.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: if var in/contains comma-separated list/array

31 Jan 2018, 03:35

PSL and CSL are bad. I don't understand why it is a pain to type an array - I don't have that issue
While CSL and PSL doesn't make any sense you could have just called it CSV which would at least mean something.
Generally speaking I would never bother reading code that contains such function names.
Readability is the most important thing when creating code and as studies have shown we humans are made for reading small words entirely.
So using CamelCase and words always is the only and the best option.
Flags or functionnames that are a combination of random letters are the perfect way for decreasing readability and the information a function name contains.
While everyone understood your first code perfectly I'm not so sure about everyone when it comes to the third or fourth example.
Also you should probably assign that array to a variable before comparing it. Not only would that make your code perfectly more readeable and solve any readability issues anyone might have - it also makes your code faster.

Code: Select all

isWeekday( string ) {
	static shortWeekDay := ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
	if string contains shortWeekDay
}
Adding descriptive names allows you to skip over specific parts of reading someone elses code ´- a must have if you want someone else to read your code.
CSL and PSL are pretty much non-descriptive. Storing that in a value will probably make me look up what your function does before
I would probably have to read your function definition - something I wouldn't have to do when you would have just used [].
And since I have bad memory I probably wouldn't only read it once or twice. So while your Array is perfectly logical for everyone your CSL and PSL function pose a problem for everyone else.
So while your Array is bulky and CSL and PSL are not the Array is still the best thing we have.
Recommends AHK Studio
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: if var in/contains comma-separated list/array

31 Jan 2018, 04:24

nnnik wrote:And since I have bad memory
I just read the two posts in this thread and all I could remember was agreeing with you nnnik :lol:.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: if var in/contains comma-separated list/array

31 Jan 2018, 04:45

- Btw 'contains' to 'StrContains' is simple enough, but 'in' to 'StrIn' causes confusion with InStr. So perhaps 'StrExact' would be better, I'm not sure if there's a better candidate word.

@nnnik:
- Would assigning to a variable be faster for a one-off use?
- I'm sympathetic re. [] being more instantly readable, but since there's no syntax for what I want, I chose a function name. Once encountered, CSL (or another name) is easy to comprehend.
- I recommend assigning variables and using comments, but not always: if ext in ["txt","xls"]
- I find "," quite taxing to type, and commonly have to use backspace to correct it, making it even slower. You could do human benchmark tests to see which you find easier to type. I could use a hotkey to convert a list into an array, but the function approach feels like the better approach.

Code: Select all

csl("a,b,c")
["a","b","c"]

csl("Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec")
["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]

csl("January,February,March,April,May,June,July,August,September,October,November,December")
["January","February","March","April","May","June","July","August","September","October","November","December"]
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
just me
Posts: 9406
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: if var in/contains comma-separated list/array

31 Jan 2018, 06:46

[b]v1 docs[/b] wrote:The "contains" operator is the same as using IfInString/IfNotInString except that multiple search strings are supported (any one of which will cause a match).

Code: Select all

InStr(Var, ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"])
see also: StrSplit -> Delimiters
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: if var in/contains comma-separated list/array

31 Jan 2018, 07:36

Asinging to a variable is faster in any case actually - when you write [] in a expression it will once again create that array again.
It might be easy for you to comprehend CSL or anything once you encountered it since it fits your style - towards me my SyntaxTree class is also very easy once encountered.
What I'm saying is that one should always choose the standard way of handling things if you want others to use your code - which is why [] is prefereable for any code you share.
The fact that you have to use Backspace etc. in such an array shows me that you might be better off using a different editor.
Recommends AHK Studio
coffee
Posts: 133
Joined: 01 Apr 2017, 07:55

Re: if var in/contains comma-separated list/array

01 Feb 2018, 00:58

just me wrote: see also: StrSplit -> Delimiters
He posted
jeeswg wrote: This would be less inconvenient to type, but still a bit bulky:
if var contains StrSplit("Mon,Tue,Wed,Thu,Fri,Sat,Sun", ",")
So "StrSplit" is bulky apparently, a function that already exists, is implemented and "splits" a string into an object given the delimiter(s) of your desires. :roll:
As a user defined function? wrap it, nobody cares. Built-in? it's not really logical to have a different function for each possible delimiter character that a user may want to use.
jeeswg wrote:- Btw 'contains' to 'StrContains' is simple enough, but 'in' to 'StrIn' causes confusion with InStr. So perhaps 'StrExact' would be better, I'm not sure if there's a better candidate word.
StrContains has always seemed more intuitive than InStr *to me*, since the descriptive version of "InStr" using a supposed Str prefix is "StrInStr", and from an object approach contains makes more sense. Following justme's example, accepting a single string or an object containing multiple strings to check whether they are contained by the string subject.
StrInList seems a more descriptive approach to StrIn. But if InStr is ever replaced with StrContains, there shouldn't really be a problem with StrIn, though the upper case i looks like a lowercase L, to the ahk unaware user, it may come across as StrLn, which doesn't exist. Either way, the check is to see whether a whole string appears in a list of words, so there's no ambiguity as to the input. It will always be a word list to match against. As it is also supposed to be a more convenient version of multiple ORed (var="something").

For RegexMatch and RegexReplace, and StrReplace, a case could try to be made for StrMatch, as it is simple matching, like StrReplace is a simple replace, or perhaps StrCompare, with the assumption that for one match/comparison you use the "=" operator and multiple comparisons you use StrMatch or whatever the name is. But if the user doesnt read the documentation, there's no hand holding that the advantage is match against a word list, i.e no advantage in StrMatch(str, "value"). So "In" or "InList" may be more "you can't screw it up" obvious.

Code: Select all

; Instead of
if (var="string1") || (var="string2") || (var=stringvar) || (var="string3")
	do

; We use
if StrMatch/StrCompare(var, ["string1", "string2", stringvar, "string3"], case, ... remaining params)
	do
"string1,string2,string3", convenient if short, guaranteed you are using string literals, all the time. Make it longer and it's just a wall of text/essay. Now add variables to it or any sort of dynamic referencing/expression and you have to start using concatenation.

Code: Select all

"string1,string2," . CONSTANT . ",string3"
"string1,string2," . CONSTANT ",string3"
stringvar1 . "," . stringvar2 . ",string1,string2"

Code: Select all

["string1", "string2", CONSTANT, "string3"]
[strinvar1, stringvar2, "string1", "string2"]
The first block is genuinely bad and it gets worse the more expressions you add, no clean division once it gets long, can't tab/space in between strings to increase legibility. Moreso, with the new continuation style of arrays, the whole thing can be even more list-like if overclarity is desired, easier editing/reading. Not sure why coding syntax should be simply ruled by a personal disability to use a keyboard, instead of following universal conventions compatible with almost anything and clearer.
jeeswg wrote: (Although for numbers, the [] syntax does remain useful.)
oArray := [1,2,3,4,5,6,7]
Above. It is always useful, e-v-e-n for s-t-r-i-n-g-s.



As for "contains" as expression (or whatever it is, operator? command?), does it return anything? is it simply bool like "is"? will it be like "~=" for regex? If there is string manipulation happening where you will need the position and you may want to "inline" inside another expression like substr, what's the feasibility of var contains "string" as an expression?
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: if var in/contains comma-separated list/array

01 Feb 2018, 02:46

- I may say more at some point.

- Type these manually:

Code: Select all

"abc,def,ghi,jkl,mno,pqr,stu,vwx,yz"

["abc", "def", "ghi", "jkl", "mno", "pqr", "stu", "vwx", "yz"]

;bonus challenge:
{abc:"def", ghi:"jkl", mno:"pqr", stu:"vwx", y:"z"}
- Anyhow, I've written some prototype scripts for converting comma-separated lists to both types of arrays. Whether you use comma-separated lists in your script or not, I would never want to type out all of the double quotes manually. In fact, due to my hotstrings system, I almost never use the shift key at all.

Code: Select all

;a,b,c,d,1,2,3,4
;["a", "b", "c", "d", 1, 2, 3, 4]
q:: ;comma-separated list to linear array
;vText := JEE_GetSelectedText()
ControlGet, vText, Selected,, Edit1, A
vOutput := "["
Loop, Parse, vText, % ","
{
	if !RegExMatch(A_LoopField, "^\d+$")
		vOutput .= Chr(34) A_LoopField Chr(34) ", "
	else
		vOutput .= A_LoopField ", "
}
;if (JEE_SubStr(vOutput, -2) = ", ")
if (SubStr(vOutput, StrLen(vOutput)-1) = ", ")
	vOutput := SubStr(vOutput, 1, -2)
vOutput .= "]"
Clipboard := vOutput
SendInput, ^v
return

;a,b,c,d,1,2,3,4
;{a:"b", c:"d", 1:2, 3:4}
w:: ;comma-separated list to associative array
;vText := JEE_GetSelectedText()
ControlGet, vText, Selected,, Edit1, A
vOutput := "{"
Loop, Parse, vText, % ","
{
	if !(A_Index & 1)
	&& !RegExMatch(A_LoopField, "^\d+$")
		vOutput .= Chr(34) A_LoopField Chr(34) ", "
	else if !(A_Index & 1)
		vOutput .= A_LoopField ", "
	else
		vOutput .= A_LoopField ":"
}
;if (JEE_SubStr(vOutput, -2) = ", ")
if (SubStr(vOutput, StrLen(vOutput)-1) = ", ")
	vOutput := SubStr(vOutput, 1, -2)
vOutput .= "}"
Clipboard := vOutput
SendInput, ^v
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
just me
Posts: 9406
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: if var in/contains comma-separated list/array

01 Feb 2018, 04:18

@coffee:
To be clear, I mentioned StrSplit() as an example for a string function which already excepts string arrays as parameters.

@jeeswg: About 'convenience':
If you look at my scripts you'll see that I rather often 'typed that manually'. Also, I usually type those 'optional' spaces and dots to separate parameters, operators, etc. It might not be 'convenient' when writing scripts, but it is 'convenient' for me when 'parsing' scripts whith my built-in parser, my eyes.
guest3456
Posts: 3453
Joined: 09 Oct 2013, 10:31

Re: if var in/contains comma-separated list/array

01 Feb 2018, 09:56

just me wrote: It might not be 'convenient' when writing scripts, but it is 'convenient' for me when 'parsing' scripts whith my built-in parser, my eyes.
:clap:

90% of programming is reading and editing code. the initial writing is of so little importance that it hardly matters. this is why style guidelines, indentation, etc is so important.

User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: if var in/contains comma-separated list/array

01 Feb 2018, 11:32

- I find comma-separated lists easier to read.
- Some arguments against ["abc", "def", "ghi"]:
(a) harder to type / easier to typo (try the typing challenge above)
(b) takes more horizontal real estate
(c) you have to convert comma-separated lists copied from elsewhere
(d) harder to visually inspect (especially when special characters or quotes/apostrophes are used)
(e) more time-consuming to edit
- Do I really want to 'objectify' something like this. JEE_MX acts like the 'in' function.

Code: Select all

if JEE_MX(vItem, "svm,svb,svy")
if JEE_MX(vItem, "setvid,sevi,svi,sv,svm,svb,svy")
if JEE_MX(vItem, "setbox,sebo")
if JEE_MX(vItem, "seturl,seur")
if JEE_MX(vItem, "setpag,sepa")
if JEE_MX(vItem, "sebl")
if JEE_MX(vItem, "ytpa,ypa")
- My plan at present is this, 7 functions:
MC,MX (contains/in) (where a comma delimiter is assumed, 2 parameters only).
StrContains/StrExact (or another name)/StrStarts/StrEnds (where you can specify the delimiter, and other options).
StrMatch (for anything else, which also acts as 'StrCompare', e.g. get items that 'match' the </<= comparison criteria).
- I don't currently use a dedicated comma-separated list to object function, because I have these functions. Simply creating an array via StrSplit, on one line, isn't too bad, but if had to use that regularly within functions or with 'contains', that would be more of a problem. Also, generally, I don't like using functions within functions, because of readability issues.
- I have been genuinely undecided re. having a 'contains' function that did or did not assume delimiting by comma by default. It was a perfect clash between convenience and conventionality. I knew that I had to have a conventional function, but in the end, I decided to have two functions, to do both.
- For me, the best compromise for AutoHotkey, would be StrContains/StrXXX functions where you could specify "D,". So StrContains/StrExact/StrMatch. And I think that StrStarts/StrEnds are absolutely worthwhile, and envisaged them shortly after I started using AutoHotkey.
- If I had to submit a quick script to the forum, StrSplit would be acceptable, so I don't mind AutoHotkey not having comma/pipe-separated list to array functions. And although I haven't advocated for such functions to be added to AutoHotkey, I think the idea of two such functions is absolutely sound. Comma-separated list to array, so CSLA, or CSL or CSA are possibilities, but then 'new CSA', could be new case-sensitive array. I appreciate that those names aren't necessarily an obvious fit with AutoHotkey.
- Re. delimited lists to arrays. I think there should be separate functions for the first 65535 Unicode characters. Actually, no I don't. Just comma and pipe. Pipes are useful when your list contains commas. Purely out of interest, are there other common delimiter characters?
- I don't find it a good argument to say that a feature is unique therefore shouldn't exist. Every programming language has unique features.
- I don't buy the argument re. one style is more widespread. If people only know AutoHotkey, then anything in AutoHotkey is perfectly normal. If people know other programming languages, they know all sorts of features unique to different languages. Something like the CSL function proposal would be extremely useful in any programming language.
Last edited by jeeswg on 01 Feb 2018, 11:42, edited 2 times in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: if var in/contains comma-separated list/array

01 Feb 2018, 11:37

You're the only one that has this problem because you got used to comma separated lists in the first place.
Comma separated lists have no real future in AHK.
Recommends AHK Studio
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: if var in/contains comma-separated list/array

01 Feb 2018, 11:52

Also, I wanted to point out the benefits of the general principle of literal text to arrays, which I use regularly.

Code: Select all

q:: ;literal text to arrays
oArray1 := StrSplit("a,b,c", ",")

vText := "
(
a=1
b=2
c=3
)"
oArray2 := Object(StrSplit(vText, ["=","`n"])*)

vText := "
(
a	1
b	2
c	3
)"
oArray3 := Object(StrSplit(vText, ["`t","`n"])*)

Loop, 3
{
	vOutput := ""
	for vKey, vValue in oArray%A_Index%
		vOutput .= vKey " " vValue "`r`n"
	MsgBox, % vOutput
}
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: if var in/contains comma-separated list/array

15 Feb 2018, 09:11

- Out of interest. If in/contains became functions, what should they be called.
in: In / StrIn (too much like InStr) / StrExact / StrWhole / something else?
contains: Contains / StrContains / something else?
- Does 'Exact' imply case sensitive, or not? Does it imply whole match, or not? Thanks.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
guest3456
Posts: 3453
Joined: 09 Oct 2013, 10:31

Re: if var in/contains comma-separated list/array

15 Feb 2018, 09:34

jeeswg wrote:- Out of interest. If in/contains became functions, what should they be called.
they shouldn't be functions, so the question is irrelevant. they are much nicer as operators which can handle multiple operand types :

Code: Select all

list := "one,two,three"
if ("one" in list)
   msgbox, true
   
arr := [1,2,3]
if (4 in arr)
   msgbox, false
   
obj := {one: "hello", two: "world"}
if (two in obj)
   msgbox, true
actually not sure how the arry/obj should be handled, since i dont believe they are two distinct types, but rather both are just objects. becuase in the example above, the array is testing for the value, but the obj is testing for the key

for string types, it could essentially replicate InStr() instead of only operating on comma separated strings, which would eliminate the need for contains. i dont think comma separated strings should be standard practice

User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: if var in/contains comma-separated list/array

23 Feb 2018, 09:50

- Regarding:
v2-thoughts
https://autohotkey.com/v2/v2-thoughts.htm

>>> Re. an array on the left-hand side. Perhaps this, the following two lines would be equivalent:

Code: Select all

vCount := ([a,b] contains [c,d])
vCount := (a contains [c,d]) + (b contains [c,d])
- So if oArrayA contains oArrayB would be equivalent to 'if at least one of the items in oArrayA contains at least one of the items in oArrayB'.
- One use would be the reverse of 'contains', 'if abcde contains one of abc,def,ghi', versus, 'if abc within one of abcde,fghij,klmno'.
- I didn't especially feel the need for 'if var contains', to become 'if list contains', so I would welcome any other ideas.
- I did feel that 'starts'/'ends' would be useful, like RegExMatch, but faster, and no escape issues.

>>> Re. how to handle a string.
- After reading v2-thoughts, it seems it has to be a comma-separated list, as it is now. I've changed my mind.
- You can do 'if var in [LiteralString]', if you want to treat commas literally. This was something that was not available in AHK v1, this makes the argument for maintaining the 'string as comma-separated list' argument stronger.
- Btw I would remove special handling for ',,'. Furthermore the ',,' syntax wasn't very effective anyway, you couldn't do this for example: ["Run,", "RunWait,"].
- 'if var1 = %var2%' became 'if (var1 = var2)', likewise 'if var1 in %var2%' could become 'if (var1 in var2)' in AutoHotkey v1/v2. With the array handling and removal of special ,, handling.
- If StrMatch functions etc existed, they could treat commas as literal, unless 'D,' was specified, because they have that additional third parameter, hence more flexibility.

>>> Also. Linear arrays v. associative arrays as input.
- A general issue is, when you use arrays in functions, should all keys be read, or just the positive integer keys *including* integer keys in the gaps that aren't assigned. I'm happy with it *always* being the positive integers (and treating keys in the gaps as blank strings), but perhaps there should be exceptions/options. I would like to hear people's opinions on this.

>>> Also. Dynamic operators.
- In some situations relating to string/numeric comparisons, I would like to be able to do something like this: if Operator(var1, var2, "<=")

- Btw basic 'does a equal b' comparisons can be fiddly:

Code: Select all

;can be fiddly
if (a+0 = b+0) ;numeric
if !("" a != b) ;as text, case insensitive/sensitive depending on A_StringCaseSense
if ("" a = b) ;as text, case insensitive
if ("" a == b) ;as text, case sensitive
;hence
if StrExact(a, b, "N")
if StrExact(a, b, "T")
if StrExact(a, b, "T CI")
if StrExact(a, b, "T CS")
- There are various examples in the help where an 'exact' match can be case sensitive or case insensitive. E.g. For the "in" operator, an exact match with one of the list items is required. So I'm happier now about the 'StrExact' name.
- @coffee: Yes, [] is good for variables (containing numbers/strings) and hardcoded numbers. StrSplit is good for hardcoded strings.
- @guest3456: There's no reason why things can't be both functions and operators. The traditional 'in'/'contains' operators require character escaping, require force expression, and force splitting if conditions across lines, obscuring the logic, and increasing indentation, and could have done with a function equivalent. E.g. re. obscuring the logic, when I went back replacing 'in'/'contains' in scripts with functions, it was hard to tell when I could/couldn't combine some of those lines with adjacent lines. In my opinion, a Between function would be better than the 'between' operator, and 'is type' might as well have been a function only.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: if var in/contains comma-separated list/array

23 Feb 2018, 10:57

jeeswg wrote:- Regarding:
v2-thoughts
https://autohotkey.com/v2/v2-thoughts.htm

>>> Re. an array on the left-hand side. Perhaps this, the following two lines would be equivalent:

Code: Select all

vCount := ([a,b] contains [c,d])
vCount := (a contains [c,d]) + (b contains [c,d])
- So if oArrayA contains oArrayB would be equivalent to 'if at least one of the items in oArrayA contains at least one of the items in oArrayB'.
- One use would be the reverse of 'contains', 'if abcde contains one of abc,def,ghi', versus, 'if abc within one of abcde,fghij,klmno'.
- I didn't especially feel the need for 'if var contains', to become 'if list contains', so I would welcome any other ideas.
- I did feel that 'starts'/'ends' would be useful, like RegExMatch, but faster, and no escape issues.
No:

Code: Select all

v := [a,b]
v contains [ [a,b], [d,e],[f,g] ] ;false
v contains [ v, [d,e],[f,g] ] ;true
thats the only possible interpretion for this code.


Comma seperated listzs are not an option that should ever be considered in a basic functionality like this due to:
  • compatability with other languages
  • having overhead ( needing to escape strings in even the most basic scenarios )
  • consistency and confusion with the incosistency of having it
Recommends AHK Studio
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: if var in/contains comma-separated list/array

29 Mar 2018, 21:14

- I've come to a conclusion. I see 5 functions. 4 simple 2-parameter functions (Contains/Ends/Exact/Starts), and 1 super-function (Match).
- For the smaller functions the model would be:
StrXXX(vText, vNeedles)
instead of:
StrXXX(vText, vNeedles, vDelim, vCaseSen, vMatch)
- The number of parameters has been reduced to keep things simple. It's useful to know that only 2 parameters are ever used, otherwise you have to spend a lot of energy reading through the function call, to check anything, including the number of parameters used.
- For things like specifying a delimiter or case sensitivity, a StrMatch function could be used.
- The three removed parameters:
-> A delimeter other than a comma can be achieved by StrSplit, this is very rare. To specify literal text use [LiteralString]. There is no special handling for ',,'.
-> Specifying case sensitivity would be done via A_StringCaseSense, this is very rare.
-> I found that returning the text of the matching item was never really needed, however, if you pass an array to vNeedles, the functions return the index of the matching item, so you could get the matching item that way.

- Here are the 4 smaller functions, and they treat a string as a comma-separated list. If anyone doesn't like contains/in etc using a comma-separated list, they'd better come up with a spectacular, effective, practical and succinct alternative. Perhaps an operator that would convert a comma-separated list into a linear array, that would be an impressive precedent for AutoHotkey to set.
- I do not think that special pipe-separated list handling is as needed, but it's worth considering.

Code: Select all

;e.g. JEE_StrStarts(vText, "http") ;comma-separated list
;e.g. JEE_StrStarts(vText, "http,www") ;comma-separated list
;e.g. JEE_StrStarts(vText, [","]) ;array containing literals
;e.g. JEE_StrStarts(vText, [vNeedle]) ;array containing literals
;e.g. JEE_StrStarts(vText, [vNeedle1, vNeedle2]) ;array containing literals
;e.g. JEE_StrStarts(vText, ["http"]) ;array containing literals
;e.g. JEE_StrStarts(vText, ["http", "www"]) ;array containing literals
;e.g. JEE_StrStarts(vText, StrSplit("http|www", "|")) ;array containing literals

JEE_StrContains(ByRef vText, ByRef vNeedles)
{
	local vKey, vValue
	for vKey, vValue in (IsObject(vNeedles) ? vNeedles : StrSplit(vNeedles, ","))
		if InStr(vText, vValue)
			return vKey
	return 0
}

JEE_StrEnds(ByRef vText, ByRef vNeedles)
{
	local vKey, vLen := StrLen(vText), vValue
	for vKey, vValue in (IsObject(vNeedles) ? vNeedles : StrSplit(vNeedles, ","))
		if !("" SubStr(vText, vLen-StrLen(vValue)+1) != vValue)
			return vKey
	return 0
}

JEE_StrExact(ByRef vText, ByRef vNeedles)
{
	local vKey, vValue
	for vKey, vValue in (IsObject(vNeedles) ? vNeedles : StrSplit(vNeedles, ","))
		if !("" vText != vValue)
			return vKey
	return 0
}

JEE_StrStarts(ByRef vText, ByRef vNeedles)
{
	local vKey, vValue
	for vKey, vValue in (IsObject(vNeedles) ? vNeedles : StrSplit(vNeedles, ","))
		if !("" SubStr(vText, 1, StrLen(vValue)) != vValue)
			return vKey
	return 0
}
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: if var in/contains comma-separated list/array

03 May 2018, 10:47

Maybe ObjCSL and ObjPSL functions? [Or ArrCSL and ArrPSL.]

Code: Select all

if vItem contains ObjCSL("a,b,c,d,e")
if (vItem contains ObjCSL("a,b,c,d,e")) ;two-way compatible
if StrContains(vItem, ObjCSL("a,b,c,d,e"))
if StrContains(vItem, StrSplit("a,b,c,d,e", ","))

if vItem contains ObjPSL("a|b|c|d|e")
if (vItem contains ObjPSL("a|b|c|d|e")) ;two-way compatible
if StrContains(vItem, ObjPSL("a|b|c|d|e"))
if StrContains(vItem, StrSplit("a|b|c|d|e", "|"))

;note: where vNeedle is one item, a string
if vItem contains vNeedle
if (vItem contains vNeedle) ;two-way compatible
if StrContains(vItem, vNeedle)
if InStr(vItem, vNeedle)

if vItem in vNeedle
if (vItem in vNeedle) ;two-way compatible
if StrExact(vItem, vNeedle) ;note: depends on A_StringCaseSense
if !("" vItem <> vNeedle)
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: if var in/contains comma-separated list/array

26 May 2018, 23:12

- I had thought that a CSL function could have dual functionality: array to comma-separated list (string) and vice versa. ["a", "b", "c"] <-> "a,b,c"
- The same would apply to PSL.

Code: Select all

q:: ;testing ArrCSL / CSL functions
oArray := ["a", "b", "c", "d", "e"]
vText := CSL(oArray)
MsgBox, % vText ;a,b,c,d,e
oArray := CSL(vText)
oArray2 := ArrCSL(vText)
MsgBox, % oArray.3 ;c
MsgBox, % oArray2.3 ;c
return

ArrCSL(vText)
{
	return StrSplit(vText, ",")
}

CSL(vText)
{
	if !IsObject(vText)
		return StrSplit(vText, ",")
	oArray := vText
	Loop, % oArray.Length()
		vOutput .= (A_Index=1?"":",") oArray[A_Index]
	return vOutput
}
- One related point. I had been thinking about function design, regarding separate (or combined) functions that work differently for linear/associative arrays.
- I noticed that there are numerous 'Obj' functions but no 'Arr' functions, and thought that the 'Arr'/'Obj' distinction could be something that I might consider.
- I don't feel strongly on the matter.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “AutoHotkey Development”

Who is online

Users browsing this forum: No registered users and 26 guests