Contains() function with multiple values


#1

Hello.
I want to read an output and if its exists on a list to do an action.
(I want to make it in case sensitive and to use contains() in order to catch and missing space)
example:

output: “the weather is nice today” or “the weather is nicetoday”
list: [nice, sunny, beautiful]

I tried to make a CASE or IF statement using contains() with no luck.
I want to make the same action if any of the values of the list appear on the output.
is there a way to create a case statement with more that one value?
something like: contains({Body},(“nice” or ”sunny” or ”beautiful”)


"Is not any of".. should I use colon, semicolon, or
#2

Contains() returns ‘true’ or ‘false’. Put your contains expression under ‘what to compare’ and then ‘compare to’ should be ‘true’.


#3

For some reason, I thought the ‘pipe’ was the symbol to split, but my quick test failed. Maybe I have my syntax incorrect.

That being said, you can still do it in one line of code, like this:


#4

I believe what you are referring to is the ‘or’ operator. I think it would look like this:

contains(Body, "nice") || contains(Body, "cool")

This would return true if either is true. ‘&&’ would require both to be true.


#5

So there you go, two alternative ways to do the same thing:

(contains(Body, "nice") ? true : (contains(Body, "cool") ? true : false))
… or …
(contains(Body, "nice") || (contains(Body, "cool") ? true : false))

I am a fan of the first method, because the extra 6 characters lets you be more specific on the output.


#6

Actually, in the second method you don’t need the ternary operator at all since the function returns true/false on its own. Its kind of redundant saying, if ‘true’ return ‘true’. Your first method, does give more control as you say in case you specifically want to change the result depending on conditions.

(contains(Body, "nice") ? true : (contains(Body, "cool") ? true : false))
… or …
(contains(Body, "nice") || contains(Body, "cool"))


#7

Touché


#8

Speaking of which…

If you’re happy with only 2 results, and condensed code is your objective, you can reduce 50% by using:
matches(Body, '/cool|nice/')

pic

(in this example, only a single pipe | is permitted between words)

Same string as before:
“cool” was not a match, but “nice” was.


Note:

  • matches() uses regular expressions, so it won’t work verbatim in every scenario…
  • contains() is a much more “newbie” friendly method

Translation:

For the uninitiated, regex is a fickle beast, so choose your path wisely…
(although there are good reference sites elsewhere, if you choose)


#9

You’re still the king!

EDIT: Question: matches() isn’t in the wiki functions list. Are there other functions not listed there that are still valid in webcore? Where might we find them? thanks!


#10

That’s worked!!
If I want to make in case sensitive to match ether cool or Cool I have to use the ‘i’ flag?
I change the regex to matches(Body, '/cool|nice/i’) with no luck.


#11

to make case insensitive, convert your string to lower case for comparison:

matches(lower(Body), '/cool|nice/')


#12

That’s was clever!:slight_smile: Thanks guys for your help.


#13

Or to make just one word case sensitive:
matches(Body, '/cool|Cool|nice/')

(pipes in the middle, and slashes at the beginning & end)

Edit: It just dawned on me that when you said, “in case sensitive”, you meant “case insensitive”.


@guxdude, I believe matches() is not in the Wiki due to all the typical problems that go along with regex and newbies. Honestly, I hope I do not regret posting that info.

IE: I would not go inserting matches() all willy-nilly in your pistons.


#14

If I would have known it was your Birthday, I would have waited 24 hours before taking back the crown, LOL


#15

LOL. Thanks!


#16

Now I am racking my brain trying to think of a piston I can write to use this information!


#17

Like a kid with a new toy, LOL


#18

Ok, I’ve greatly simplified this example trying to figure out this exact example. I have this:

matches('a b c d', 'a') with no slashes evaluates TRUE, but…
matches('a b c d', '/a/') with slashes evaluates FALSE, and…
matches('a b c d', '/a|b/') evaluates FALSE.

Shouldn’t these last two also evaluate true?

I had a piston that matched weather conditions that was greatly simplified using this method, but it’s not working after moving to Hubitat. I can’t even get the expressions to evaluate correctly.

Any thoughts?


#19

I would try a modified version of what I posted above… Maybe something like:

matches(var, '/a/')
matches(var, '/a|b/')

(var = a string variable previously set)


#20

This is still evaluating false. Where is the evaluation actually computed? On the dashboard or on the hub?