JavaScript OR (II) (this OR this OR this... do this) [duplicate] - operator-keyword

var choice1 = prompt("Enter choice 1");
var choice2 = prompt("Enter choice 2");
if (choice1 === "x" && choice2 === ("a" || "b" || "c")) {
alert("Good job!");
}
Assume the user input x for choice1 and c for choice 2.
The above is a simple example to highlight my issue. I know it doesn't work but my question is why? Javascript won't compare the multiple || statements within () against choice2. Why not? The logic in my mind is choice2 is the same type and value (===) as "a" or "b" or "c".
The way I got it working was this:
(choice1 === "x" && ((choice2 === "a") || (choice2 === "b") || (choice3 === "c"));
Please help me understand why when using multiple ||'s, you need to explicitly write out each || scenario as opposed to putting a bunch within () as I tried up top. Thanks.

It just doesn't work that way, you can't compare one value against multiple other values using OR, you have to compare each value individually.
The closest you'll get is using Array.indexOf
if ( ['a', 'b', 'c'].indexOf(choice2) != -1 )
The reason it doesn't work is because OR and AND checks for a truthy value, so in
('a' || 'b' || 'c') // return "a"
a is a truthy value, so the OR never proceeds, it doesn't have to, it already has a truthy value so the expression is true, and you're left with a, the rest is discarded

In JavaScript, if you do this
var a = null;
var b = {};
var c = "haha"
var d = a || b || c;
the value of d will be b. Expressions of type var1 || var2 || var3 return with the value of first not null or not undefined value.
So, in you case choice2 === ("a" || "b" || "c") is same as writing choice2 === "a".

(object || object) syntax is something like null check operator not for condition check in javascript.
so
console.log(null || "b") would log b
console.log(undefined || "b") would log b
console.log(("a" || "b")) would log a
console.log(null || "b")
console.log(undefined || "b")
console.log(("a" || "b"))
Your condintion(below) will only work if choice2 is "a" and choice1 is "x".
if (choice1 === "x" && choice2 === ("a" || "b" || "c")) {
alert("Good job!");
}

What is in the brackets get evaluated first so ("a" || "b" || "c") will evaluate to "a" because what you are effectively saying is return either "a" or "b" or "c" so it returns "a" because that is first.
I believe what you are expecting is ("a" || "b" || "c") to act some sort of set operation but JavaScript doesn't have that feature so your code choice2 === ("a" || "b" || "c") will only ever be true if the user chose "a". The best way to compare multiple values with choice2 is to store "a","b" and "c" in an array and see if choice2 exists in it. ["a","b","c"].indexOf(choice2) != -1.
In most languages you won't even be able to compare three strings but JavaScript does everything it can to not throw exceptions so it doesn't cause the user of the website to realise there is a problem with the page so it will try and compare the three strings as you would compare three booleans but instead of returning a boolean it returns a string. I would avoid that syntax completely as it would confuse most developers not familiar with the weird ways of JavaScript.

Related

Spark Scala compiler not complaining about double vs. triple equals

I get a compiler error if I try this
df.filter($"foo" == lit(0))
forgetting that I need a triple equals in Spark.
However, if I do this, I get the wrong answer but no error:
df.filter($"foo".between(baz, quux) || $"foo" == lit(0))
Can someone explain why compile-time checks help me in the first case, but not the second?
Because $"foo" == lit(0) is always evaluated as Boolean = false.
So in the first case, you trying to call method filter by passing a Boolean whereas it expects a string expression or column expression. Thus you get an error.
Now in the second, case:
$"foo".between(baz, quux) || $"foo" == lit(0) is evaluated as:
(((foo >= baz) AND (foo <= quux)) OR false)
which is accepted beacause you doing an OR || between a column expression ($"foo".between(baz, quux)) and a literal boolean false.
In other words, it is interpreted as $"foo".between(baz, quux) || lit(false)

How to write an If-Else loop involving multiple conditions in an idiomatic Scala way?

I'm a Scala noob and trying to write the following piece of validation code in a Scala idiomatic way.
How do I make use of Options and case-match in such a scenario ? Or is it not possible to avoid a null check here ?
var flag = True
// set flag to true when exactly 1 of (c1,c2) is present
if (c1 == null and c2 == null) or (c1 != null and c2 != null){
flag = False
}
// other code continues that manipulates flag
First off, we like to avoid nulls by nipping them off as early as possible.
val o1 = Option(/*code that retrieved/created c1*/)
val o2 = Option(/*code that retrieved/created c2*/)
Then code that "manipulates" mutable variables is a bad idea, but as you didn't include that part we can't offer better solutions for it.
val flag = o1.fold(o2.nonEmpty)(_ => o2.isEmpty) &&
//other code continues that calculates flag value
That's exactly what XOR does
val flag = c1 == null ^ c2 == null
As #jwvh mentioned, would be great to avoid nulls in Scala as well.
val o1 = Option(c1) // turns null into None
val o2 = Option(c2)
val flag = o1.isDefined ^ o2.isDefined
Note, in both examples you don't need to use var.

Scala filtering on 2 conditions to remove strings from a list

This feels like it should be very simple but after several variations I'm unable to return the correct result.
I have a list of strings that I'm trying to filter on and a Set of strings that I'm using as a blacklist. If any of the strings in my list are in the black list then I want to ignore them and only return the ones that are not present. In addition to this I have another case that I need to check for so I need to make sure its not in the black list and also not condition two.
val strings = List("something", "something.else", "something-else" )
val blacklist = Set(".else", ".new", ".old")
I’m trying to do something like:
strings.filter(f => !f.endsWith("-else"))
to leave just "something" and "something.else" but I can’t seem to return "something" by itself.
strings.filter(
f => !f.endsWith("-else") && !blacklist.exists(suffix => f.endsWith(suffix))
)
Or a shorter (but identical) version:
strings.filter(f => !f.endsWith("-else") && !blacklist.exists(f.endsWith))
I understand you want to remove an element if it ends with something that is in your blacklist.
You could try something like
strings.filter {x => (blacklist map {word => !(x endsWith word)} reduce( (a,b) => a && b ) ) }
with another condition, for example x.length >= 2
strings.filter {x => (blacklist map {word => !(x endsWith word)} reduce( (a,b) => a && b ) ) && x.length >= 2}

Coffee Existential Operator different compliations [duplicate]

This question already has an answer here:
How does CoffeeScript's existential operator work?
(1 answer)
Closed 8 years ago.
Similar to this topic:
CoffeeScript Existential Operator and this
The coffeescript, I'm having a problem using the elvis operator:
foo = ->
y = foo()
console.log 'y is null' unless y?
console.log 'x is null' unless x?
Compiles to:
var foo, y;
foo = function() {};
y = foo();
if (y == null) {
console.log('y is null');
}
if (typeof x === "undefined" || x === null) {
console.log('x is null');
}
Output:
y is null
x is null
So the problem is that since y is assigned earlier that coffee takes the shortcut and assumes that y cannot be undefined. However, it is valid to return undefined from a function.
Is there a "safer" way to check that y is also not undefined?
UPDATED
Clarified Examples and Explanation:
From the comments, in the first if statement (y == null) is using double equal instead of ( x === null) triple equal, as in the second if statement. Clever.
? operator always checks if the value is neither null nor undefined.
y == null is absolutely correct way to check that the value of y is either null or undefined in JavaScript.
For example, the following CofeeScript code checks only for null values:
do_something() if y is null
which compiles to
if (y === null) do_something();
So, while y? (y == null in JS) checks for both null and undefined, y isnt null (y !== null in JS) checks only for null.
Check this answer for more detailed information.
See this answer for more info about equality checks in JavaScript.

How to check whether key or value exist in Map?

I have a scala Map and would like to test if a certain value exists in the map.
myMap.exists( /*What should go here*/ )
There are several different options, depending on what you mean.
If you mean by "value" key-value pair, then you can use something like
myMap.exists(_ == ("fish",3))
myMap.exists(_ == "fish" -> 3)
If you mean value of the key-value pair, then you can
myMap.values.exists(_ == 3)
myMap.exists(_._2 == 3)
If you wanted to just test the key of the key-value pair, then
myMap.keySet.exists(_ == "fish")
myMap.exists(_._1 == "fish")
myMap.contains("fish")
Note that although the tuple forms (e.g. _._1 == "fish") end up being shorter, the slightly longer forms are more explicit about what you want to have happen.
Do you want to know if the value exists on the map, or the key? If you want to check the key, use isDefinedAt:
myMap isDefinedAt key
you provide a test that one of the map values will pass, i.e.
val mymap = Map(9->"lolo", 7->"lala")
mymap.exists(_._1 == 7) //true
mymap.exists(x => x._1 == 7 && x._2 == "lolo") //false
mymap.exists(x => x._1 == 7 && x._2 == "lala") //true
The ScalaDocs say of the method "Tests whether a predicate holds for some of the elements of this immutable map.", the catch is that it receives a tuple (key, value) instead of two parameters.
What about this:
val map = Map(1 -> 'a', 2 -> 'b', 4 -> 'd')
map.values.toSeq.contains('c') //false
Yields true if map contains c value.
If you insist on using exists:
map.exists({case(_, value) => value == 'c'})
Per answers above, note that exists() is significantly slower than contains() (I've benchmarked with a Map containing 5000 string keys, and the ratio was a consistent x100). I'm relatively new to scala but my guess is exists() is iterating over all keys (or key,value tupple) whereas contains uses Map's random access