if var in/contains comma-separated list/array

Post a reply

Confirmation code
Enter the code exactly as it appears. All letters are case insensitive.
Smilies
:D :) ;) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :!: :?: :idea: :| :mrgreen: :geek: :ugeek: :arrow: :angel: :clap: :crazy: :eh: :lolno: :problem: :shh: :shifty: :sick: :silent: :think: :thumbup: :thumbdown: :salute: :wave: :wtf: :yawn: :facepalm: :bravo: :dance: :beard: :morebeard: :xmas: :HeHe: :trollface: :cookie: :rainbow: :monkeysee: :monkeysay: :happybday: :headwall: :offtopic: :superhappy: :terms: :beer:
View more smilies

BBCode is ON
[img] is OFF
[flash] is OFF
[url] is ON
Smilies are ON

Topic review
   

Expand view Topic review: if var in/contains comma-separated list/array

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

Post by guest3456 » Today, 18:15

jeeswg wrote:- I'd want something built-in

then there is nothing to talk about. either build it in yourself and submit a pullrequest, or wait for lexikos to build it in

jeeswg wrote:so that scripts can be easily shared. So no custom functions.

just include your custom function in the script and it can be easily shared.

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

Post by jeeswg » Today, 10:45

- Thanks for your response.
- I'd want something built-in, so that scripts can be easily shared. So no custom functions.
- RegEx is slow. (Although is StrSplit slower? I'll do some benchmark tests.)
- RegEx requires character escaping.
- RegEx requires fiddly ^, $ and parenthesis adding.
- RegEx handles string comparisons only. The 'in' operator might support handling for numeric comparisons.
- So StrSplit is the best existing option.

- I would really appreciate if people think about this problem, and try to come up with any syntax suggestions. I do find this question a tricky one.
- Another idea would be something like: var match "X,)abc,def,ghi". That would check for an exact match, comma-delimited. A kind of home-grown simpler RegEx for C/E/S/X (contains/ends/starts/exact).

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

Post by guest3456 » Today, 10:36

there are function and regex alternatives in this thread:

https://autohotkey.com/boards/viewtopic ... 37&t=23033

using a C/P suffix is awful

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

Post by jeeswg » Today, 06:50

- This is the one important AHK v2 issue I've seen without an easy solution.
- These are my 2 best solutions at present, please be mature about any feedback.
- If you specify 1 needle for contains/in, it should be relatively easy to add a 2nd needle without rewriting everything.

Code: [Select all] [Expand]GeSHi © Codebox Plus

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

Post by jeeswg » 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] [Expand]GeSHi © Codebox Plus


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

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

Post by jeeswg » 03 May 2018, 10:47

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

Code: [Select all] [Expand]GeSHi © Codebox Plus

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

Post by jeeswg » 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] [Expand]GeSHi © Codebox Plus

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

Post by nnnik » 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]GeSHi © Codebox Plus

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]GeSHi © Codebox Plus

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

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

Post by jeeswg » 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]GeSHi © Codebox Plus

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] [Expand]GeSHi © Codebox Plus


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

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

Post by guest3456 » 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] [Expand]GeSHi © Codebox Plus



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

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

Post by jeeswg » 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.

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

Post by jeeswg » 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] [Expand]GeSHi © Codebox Plus

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

Post by nnnik » 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.

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

Post by jeeswg » 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]GeSHi © Codebox Plus

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.

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

Post by guest3456 » 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.

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

Post by just me » 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.

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

Post by jeeswg » 01 Feb 2018, 02:46

- I may say more at some point.

- Type these manually:

Code: [Select all]GeSHi © Codebox Plus

"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] [Expand]GeSHi © Codebox Plus

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

Post by coffee » 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]GeSHi © Codebox Plus

; 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]GeSHi © Codebox Plus

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


Code: [Select all]GeSHi © Codebox Plus

["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?

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

Post by nnnik » 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.

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

Post by just me » 31 Jan 2018, 06:46

v1 docs 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]GeSHi © Codebox Plus

InStr(Var, ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"])

see also: StrSplit -> Delimiters

Top