Javascript conditions issues - javascript

I have a situation in my code where I have several conditions for 3 variables, let's say a, b and c.
I've implemented else if conditions for each case when one of three is false and for when all three are true and for when all three are false. But the problem is that I need to implement conditions also for when 2 out of 3 are false and following the order of a, b and c I need to show specific message for the first in order that is false.
For example, a becomes false, then b becomes false and c remains true, I need to show a specific message for a false. Other case: when b becomes false then a becomes false and c remains true, I need to show a specific message for a false, when c becomes false and b becomes false, I need to show a specific message for b.
How can this be achieved?
Code example
if (a && b && c) {
setOrder(format(order));
} else if (!a && b && c) {
setOrder("orderAlternateNumber");
} else if (!b && a && c) {
setOrder("orderNewNumber");
} else if (!c && a && b) {
setOrder("someOtherNumber");
} else if (!c && !a && !b) {
setOrder("");
}

You can combine these variables into a single number with ones and zeroes and use a simple dictionary lookup for the order parameter:
let n = 1000 + (a * 100) + (b * 10) + (c * 1)
order = {
1111: format(order), // true,true,true,
1011: "orderAlternateNumber", // false,true,true
1101: "orderNewNumber", // true,false,true etc...
1110: "someOtherNumber",
1000: '',
}
setOrder(order[n])

I am not entirely sure what your scenario is, you example is somewhat vague because you don't give a lot information about your actual issue. However based on:
For example, a becomes false, then b becomes false and c remains true, I need to show a specific message for a false.
I would suggest the following. Instead of checking all combinations a, b and c. You can also check them separately.
let error;
if (!a) error ??= "something wrong with a";
if (!b) error ??= "something wrong with b";
if (!c) error ??= "something wrong with c";
if (error) {
// do something with error message
} else {
// handle success
}
The above stores a single error message depending on the first error it encounters. ??= only assigns a value if the current value if nullish. But you could also collect them by storing them in an array.
const errors = [];
if (!a) errors.push("something wrong with a");
// ...
if (errors.length != 0) {
This might not be what your looking for, it's hard to say what is since you withhold your actual scenario.

On the function that changes a, b and c, you need to have a condition.
If one of them is going to be set to false, you have to check if another one, and only one is already false. If there is another false, you can set the message according to this one and commit the change for the second parameter to be false.
If im not clear, you might want to add code example for the function that controls a, b and c for my better understanding.

Related

Having trouble understanding this javascript destructuring statement

I'm working with a react/redux sample project and since I'm kind of new to Javascript, my exposure to some of the shorthanded ES6 javascript is limited.
The statement I am having trouble following is this:
function mapStateToProps(state) {
const { selectedSubreddit, postsBySubreddit } = state;
// This part here is confusing to me
const { isFetching, lastUpdated, items: posts } = postsBySubreddit[
selectedSubreddit
] || {
isFetching: true,
items: []
};
return {
selectedSubreddit,
posts,
isFetching,
lastUpdated
};
}
I mostly understand the purpose of this function but I'm not sure what's going on in that part that I have a comment in.
What I gathered so far is that postsBySubreddit is an array that we are getting an element from based on selectedSubreddit. From that element, we are 'extracting' isFetching, lastUpdated, and items (while aliasing it to posts simultaneously). The thing that throws me off is the || operator and the statement that follows it in the curly braces.
Is this an OR condition? If it is, are we saying that if postsBySubreddit[selectedSubreddit] === undefined, we're giving isFetching the value of true and items an empty array?
Your understanding is almost correct. Until the || operator, you're correct. But for the || operator,
if postsBySubreddit[selectedSubreddit] === undefined, we're giving isFetching the value of true and items an empty array
Not necessarily undefined, if postsBySubreddit[selectedSubreddit] is falsy, e.g. 0, '', false, null, undefined, NaN. Note that [] and {} are truthy. (to easily check if you've forgotten, you can type !!NaN in the dev console or node interpreter).
let a = b || c is equivalent to:
let a;
if (b)
a = b;
else
a = c;
Similarly, let a = b || {x: 0, y: 1} is equivalent to
let a;
if (b)
a = b;
else
a = {x: 0, y: 1};
The || operator means to run the next statement if the previous one is false.
Just look at this:
if (thing == "ok" || otherthing == "notok") {
I think that you know what this means. Enter the block if either statement is true. The way it "runs" is by first checking the left statement (thing == "ok") and if is false, then run the next statement (otherthing == "notok").
The same thing can be done to assign to variables:
var result = thing == "ok" || otherthing == "notok";
This thing will make result be true if the left or right statement returns true, following the same logic as I explained above.
Now, if we go further with this logic, we can do this:
var result = FIRST_STATEMENT || SECOND_STATEMENT;
This will run the FIRST_STATEMENT, get the value and check if is not false. If the result is not false, will run the SECOND_STATEMENT and return the value. if the FIRST_STATEMENT is not false, will return that value instead (because will not run the SECOND_STATEMENT).
In short, the || operator will evaluate statements from left to right and return the first one that is not false.
PD: Note that null, undefined, "", NaN and 0 is the same as a false statement.
PD2: To clarify, none of these values will be triple equal (===) to each other.

combine multiple && conditions into 1

Is there a better way in Javascript to do null check on multiple elements I want to
a=null; b=null;....n=null;
So in total I have 14 variables set to null initially and I want to apply just one solution to all of them if they are ```null``.
if (a=== null && b=== null&& c=== null&& d=== null&& e=== null &&...&& n===null){
// set some field to false
}
is there a better way to check for null, as this may get cumbersome if we have more arrays added
Thanks!
Create a an array of arrays, iterate it using Array.every(), and do something if all item values are null:
if([a, b, c, ... n].every(a => a === null)) {
// set some field to false
}
If you're new to JS, in JS, values can be "falsey" or "truthy". if / while / for will run if the value it's supposed to evaluates to "truthy." There are few "falsey" values in JS, and the rest are considered "truthy." The false values are:
undefined
0
NaN
null
''
false
(I believe I got them all. Think of "six sins": there are six of these)
So check the following code, and what their outcomes are:
if(0) console.log('yay') // won't run
if(false) console.log('yay') // won't run
if(null) console.log('yay') // won't run
if('') console.log('yay') // won't run
if(NaN) console.log('yay') // won't run
if([]) console.log('yay') // will run
if('0') console.log('yay') // will run
This is a long winded way of saying if you want to do something based on whether array is empty or not, try the following:
let arr = [1,2,3,4]
if(arr.length){
//do stuff if array is not empty
} else {
// do stuff if array is empty
}
Now to actually solve the problem for you, do the following:
const masterArray = [a, b, c, d, ... , n];
let length = 0;
masterArray.forEach(subarr=>{
length += subarr.length;
})
//At this point, if no array had any elements, length would be 0
if(length === 0){
// do stuff
}

I'd like to make sense of a JS nullreference exception

An exception occurred several times inside the following function, running in the (Chrome) browsers of our users. NB the code is minified, I've just added newlines for readabilily.
function a(c, b, e, f) {
for (var d in b) {
if (c && _.isObject(b[d]) === true && _.isArray(b[d]) === false) {
a(c[d], b[d], e, d + ".")
} else {
if (!c || _.isEqual(c[d], b[d]) === false) {
e.push({
name: f + d,
value: b[d]
})
}
}
}
return e
}
The exception was: TypeError: Cannot read property 'beginning' of null
So far my analysis is this:
Known fact: beginning is one of the values of the d variable (a
property of b).
So, the exception occurred when evaluating b[d]or c[d]
Inside the for loop, c can be null, but not b (b null => no loop)
So, the only way to trigger that exception is to have a null c
If c is null, we have to take the else path
If c is null, !c is truthy, so _.isEqual(...) should not be evaluated (see Is that js expression safe: if( !x || doSomething( x[prop], y[prop] ) === false )).
At that point, I've reached a dead end in my reasoning. The exception should not happen. I probably made a mistake somewhere along the line, but where ?
NB: the problem seems to be fixed (I can't reproduce it, so I can't be sure), just by changing the code a bit, adding a separate 'is c null ?' test before the if...else, but that's not very satisfying.

Custom sorting jqgrid

I am trying to write a function to sort my column because it has specific values. I have a lot alarms, and they have 2 states: Active and Not Active. And in case of "Active" I write to column string - "Active" and in case of "Not active" I write to column last seen date like: 24 Jun 2014, 07:36:14.
And the problem that when I use default jqgrid sort function, it sorts unproperly, because I have 2 types data.
And I found that in jqgrid I can write custom sorting functions. So here is my efforts:
var timeRegexPatter = /(\d{2})-(\d{3})-(\d{4}) (\d{2}):(\d{2}):(\d{2})/;
var alarmLastSeenSort = function(a, b, direction) {
if (a === 'Active') { //how to use directions properly?
return 1;
}
else if (b === 'Active') {
return -1;
}
var timeArrA = a.match(timeRegexPatter); //array A
var timeArrB = b.match(timeRegexPatter); //Array B
//here should be probably transform time regex into timestamp and compare it,
//is there any predefined functions to do this
}
Caveat: I don't know the jqgrid library specifically.
In general, though, a sort function should return 1, 0, or -1 based on the comparison of the two incoming arguments. Assuming an ascending sort:
If a < b, return -1
If a == b, return 0
If a > b, return 1
where the <, ==, and > operators refer to your desired collating order of the objects, which may not necessarily be the same as strict mathematical or string comparisons. For example, you may have an object that you want to sort by name, then ID, which would involve comparisons of two different properties with different types.
In your case, you have two axes on which to sort, "activeness" and "timestamp". So your first question is: how should an active compare to an inactive? It doesn't make sense to compare one item at a time, unless it's to forbid sorting of objects that are not the same type and throw an error.
Once you dispose of the "activeness" sort, you can move on to comparing timestamps in the case of an inactive item.
Again, I don't know jqgrid specifically, but I assume direction refers to "ascending" or "descending" order. That will determine whether you return a 1 (ascending) or -1 (descending) for the a > b case.
Demo here.
var i, sortedArray;
var testArray = [
'active',
'2014-06-25 01:23:45',
'active',
'active',
'2013-01-31 12:34:56',
'2014-06-25 02:34:45'];
var comparitor = function(a, b, direction) {
console.log('comparitor(a, b, direction)::', a, b, direction);
// Replace this with whatever test allows you to determine whether you're sorting in ascending or descending order
var after = direction === 'descending' ? -1 : 1;
// If both are active, neither should be reordered with respect to the other
if (a === 'active' && b === 'active') {
console.log('Both a & b are active; returning 0');
return 0;
}
// We know at least one is "inactive". Assume "active" should come before "inactive".
if (a === 'active') {
console.log('a is active; returning -1');
return -1 * after;
} else if (b === 'active') {
console.log('b is active; returning 1');
return after;
}
// We know that neither one is active, and can assume both are date strings. You could convert to dates here, but why, since your dates are already in a format that sorts quite nicely?
if (a === b) {
console.log('a === b; returning 0');
return 0;
}
console.log('a !== b; returning either 1 or -1');
return a > b ? after : -1 * after;
}
sortedArray = testArray.sort(comparitor);
for (i = 0; i < sortedArray.length; i++) {
console.log(i + ' = ' + sortedArray[i]);
}

Why does ( true && 1 ) return 1, but ( 1 && true ) returns true?

In C I know true and false evaluate to 1 and 0 respectively. show in this case just prints to the screen... Not sure what's going on here. I'm expecting to get true back. This 1 is messing up my karma.
show(1 && true);
true
show(true && 1);
1
Simply put - that's how && is defined. In Javascript, a && b returns a if a is falsy and b if a is truthy.
Conversely a || b returns a if a is truthy and b if a is falsy.
This makes sense intuitively - if a is false in a && b, then why bother reading the rest of the expression? You already know the whole thing is false. So just return false. But Javascript makes the decision to return a, which is falsy, instead of making up the value false to return out of nowhere.
This is based on short-circuit evaluation common to all C-style languages.
It allows for much expressiveness in Javascript. For instance this pattern:
var foo = function(opts) {
opts = opts || {}
// ...
}
Implements an optional parameter opts. If opts is not passed in at all, opts = opts || {} will set opts to {}, so the rest of the code does not have to know opts wasn't passed.
In long-hand it is equivalent to the following:
var x = a || b; // is equivalent to
var x;
if(a) {
x = a;
}
else {
x = b;
}
and
var y = a && b; // is equivalent to
var y;
if(!a) {
y = a;
}
else {
y = b;
}
Therefore Javascript can be much more terse than C or Java, because simple if statements can be replaced by || or && entirely. Sometimes this makes the code more terse and less readable and more like Perl, other times it allows for new Javascript patterns, like opts = opts || {}.
Another use is in patterns like
var displayName = user.fullname || user.email;
Which means "use the full name if available; if not, fall back to email." I personally find this expressive and readable, but it's arguably terse and obscure depending on which part of the Javascript community you hail from. Because of examples like this, and essentially the fact that truthy values are far more diverse then falsy values, using short-circuit || is much more common than short-circuit &&, as in your question.

Categories