Ternary Operator - 3 conditions - javascript

I'd like to rewrite this with a ternary operator. I believe I need 2 operators.
if (a.quantity > b.quantity) {
return -1;
} else if (a.quantity < b.quantity) {
return 1;
} else {
return 0;
}
Ternary
return (a.quantity > b.quantity) ? -1 : (a.quantity < b.quantity) ? 1 : 0;
would this be the equivalent?

If you need the value for sorting, you could take the delta of the two values:
data.sort((a, b) => a.quantity - b.quantity); // ascending
data.sort((a, b) => b.quantity - a.quantity); // descending

Yes those are equivalent
return (a.quantity > b.quantity) ? -1 : (a.quantity < b.quantity) ? 1 : 0;

Related

JavaScript return condition

Is it possible to have conditions in return in JavaScript?
Like in this case:
if
(A > 0 || B > 0)
return "A";
else return "C"
As long as A or B is > 0 return the one that is > 0 (so A or B). Is that possible? Like another condition as return, for example?
Maybe this is similar to what you are trying to do. My function eval() takes two parameters A and B, and checks different conditions to see which is the positive number. I am using the Logical AND && instead of || because I want my code to know the value of each parameter in each condition.
function eval(A, B) {
if (A > 0 && B <= 0) {
return 'A';
}
if (A <= 0 && B > 0) {
return 'B';
}
if (A > 0 && B > 0) return "Both A and B are positive numbers";
}
console.log(eval(2, -5));
console.log(eval(0, 8));
console.log(eval(1, 1));
Try this.
return (A > 0 || B > 0) ? "A" : "C"
It's a ternary operator. Here you have more information:
Conditional (ternary) operator
if(A > 0 || B > 0)
return A > 0 ? "A" : "B";
else return "C";

Try to figure it out how to translate a long ternary operator with more than one condition into long if statement

I found online this snippet and I'm trying to figure it out how to translate it in a plan if statement:
return a.price > b.price ? 1 : a.price === b.price ? a.name > b.name ? 1 : -1 : -1;
In my opinion, if I had written an if statement:
if (a.price > b.price) {
return 1;
} else if (a.price === b.price) {
return 1;
} else if (a.name > b.name) {
return 1;
} else {
return -1;
}
But I'm not quite sure what it means a question mark and right after another question mark, same problem with a colon. I get that, the colon, in this case, could be an else if statement (in that order), but what about the question mark? any hint?
Grouping it like this will help
a.price > b.price ? 1 : (a.price === b.price ? (a.name > b.name ? 1 : -1) : -1)
a.price > b.price ? 1 : x
x = a.price === b.price ? y : -1;
y = a.name > b.name ? 1 : -1;
The translated IF ELSE would be
if(a.price > b.price){
return 1
} else {
if(a.price === b.price){
if(a.name > b.name){
return 1;
} else {
return -1;
}
} else {
return -1;
}
}
Your first part is right, but the next isn't. This:
a.price === b.price ? a.name > b.name ? 1 : -1 : -1;
separated out, looks like:
a.price === b.price
? (
a.name > b.name
? 1
: -1
)
: -1;
The inner conditional is a.name > b.name ? 1 : -1.
If the prices are not equal, -1 is returned. Otherwise, the names are compared. To translate this correctly:
if (a.price > b.price) {
return 1;
}
if (a.price !== b.price) {
return -1;
}
if (a.name > b.name) {
return 1;
}
return -1;
If this is being used for a .sort callback, another option which is equivalent to the above is:
return a.price - b.price || a.name.localeCompare(b.name)

Making compare() function more elegant

I have this code:
function compare (a, b) {
let comparison = 0;
if (a.essentialsPercentage < b.essentialsPercentage) {
comparison = 1;
} else if (a.essentialsPercentage > b.essentialsPercentage) {
comparison = -1;
} else {
if (a.skillsNicePercentage < b.skillsNicePercentage) {
comparison = 1;
} else if (a.skillsNicePercentage > b.skillsNicePercentage) {
comparison = -1;
} else {
if (a.startDate > b.startDate) {
comparison = 1
} else if (a.startDate < b.startDate) {
comparison = -1
}
}
}
return comparison;
}
What would be the most elegant way of writing it? It doesn't seems nice at the moment.
Assuming this is being used as the comparison function for Array.prototype.sort(), only the sign of the result matters, it doesn't have to be specifically -1 or 1. So instead of if and else, you can simply subtract the numbers.
compare(a, b) {
let comparison = b.essentialPercentage - a.essentialPercentage;
if (comparison == 0) {
comparison = b.skillsNicePercentage - a.skillsNicePercentage;
if (comparison == 0) {
comparison = a.startDate - b.startDate;
}
}
return comparison;
}
If any of the properties are strings rather than numbers, you can use localCompare instead of subtraction.
This tiny function (or the equivalent <=> operator) is perhaps the most obvious lack in the js standard library:
// returns 1 if a > b, -1 if a < b, 0 if a == b
let cmp = (a, b) => (a > b) - (a < b)
Once you have defined it, chained comparisons are very easy:
compare = (a, b) =>
cmp(a.essentialsPercentage, b.essentialsPercentage)
|| cmp(a.skillsNicePercentage, b.skillsNicePercentage)
|| cmp(a.startDate, b.startDate)
If you wanted to you could use a switch statement to keep each one of your cases nice and organized. This would be a "cleaner" method but not necessarily the most correct method. See this thread --> https://stackoverflow.com/a/2312837/11263228
Alternatively, you could create separate functions that will check each of your cases. For example, having a function that takes in a.skillsNicePercentage and b.skillsNicePercentage as parameters and returns true/false. This would be cleaner and also reusable!
You could generalize this in a simpler function that takes an array of field names and sorts the overall array based on those fields, in order. The code below takes some inspiration from the Mongoose database library and allows the - prefix on a field name to sort descending instead of the default ascending order. It also only works for numbers and strings; if you want to support other types, you'll have to extend the code.
function multiSort(fields) {
return (a,b) => {
let result = 0;
for (let i = 0; result === 0 && i < fields.length; ++i) {
let fieldName = fields[i];
if (fieldName.charAt(0) === '-') {
fieldName = fieldName.substring(1);
if (typeof a[fieldName] === 'string') {
result = b[fieldName].localeCompare(a[fieldName]);
}
else {
result = b[fieldName] - a[fieldName];
}
} else {
if (typeof a[fieldName] === 'string') {
result = a[fieldName].localeCompare(b[fieldName]);
}
else {
result = a[fieldName] - b[fieldName];
}
}
}
return result;
};
}
This higher-order function will take an array of fields and return a function that sorts by those fields, in order, for strings and numbers, optionally with a field name prepended by - to sort that field in descending order. You'd use it like this:
someArrayValue.sort(multisort(['essentialsPercentage', 'skillsNicePercentage', '-startDate']));
Based on the logic in your comparison, this should work
function compare (a, b) {
let comparison = a.skillsNicePercentage == b.skillsNicePercentage ? (a.startDate - b.startDate) : b.skillsNicePercentage - a.skillsNicePercentage
let comparison1 = a.essentialsPercentage == b.essentialsPercentage ? b.skillsNicePercentage - a.skillsNicePercentage : comparison
return comparison1;
}
Try
function compare(a, b) {
let c= b.essentialsPercentage - a.essentialsPercentage;
let d= b.skillsNicePercentage - a.skillsNicePercentage;
let e= a.startDate - b.startDate
return Math.sign(c||d||e);
}
function compareNew(a, b) {
let c= b.essentialsPercentage - a.essentialsPercentage;
let d= b.skillsNicePercentage - a.skillsNicePercentage;
let e= a.startDate - b.startDate
return Math.sign(c||d||e);
}
function compareOld(a, b) {
let comparison = 0;
if (a.essentialsPercentage < b.essentialsPercentage) {
comparison = 1;
} else if (a.essentialsPercentage > b.essentialsPercentage) {
comparison = -1;
} else {
if (a.skillsNicePercentage < b.skillsNicePercentage) {
comparison = 1;
} else if (a.skillsNicePercentage > b.skillsNicePercentage) {
comparison = -1;
} else {
if (a.startDate > b.startDate) {
comparison = 1
} else if (a.startDate < b.startDate) {
comparison = -1
}
}
}
return comparison;
}
// TESTS
a={essentialsPercentage:2,skillsNicePercentage:2,startDate:new Date(0)};
tests=[
{essentialsPercentage:2,skillsNicePercentage:2,startDate:new Date(0)},
{essentialsPercentage:2,skillsNicePercentage:2,startDate:new Date(+10000)},
{essentialsPercentage:2,skillsNicePercentage:2,startDate:new Date(-10000)},
{essentialsPercentage:2,skillsNicePercentage:2,startDate:new Date()},
{essentialsPercentage:2,skillsNicePercentage:3,startDate:new Date()},
{essentialsPercentage:2,skillsNicePercentage:1,startDate:new Date()},
{essentialsPercentage:3,skillsNicePercentage:1,startDate:new Date()},
{essentialsPercentage:1,skillsNicePercentage:1,startDate:new Date()},
]
tests.map(b=> console.log(`old: ${compareNew(a,b)} new:${ compareOld(a,b)}`));

javascript broken syntax

Alright, I or someone I work with broke the syntax here somewhere, and I'm not sure where, as the debugger is giving me some random garble as the error. Anyway here is the function, I think I'm missing a bracket somewhere, but this is just evading me for some reason.
var sort_by = function(field, reverse, primer) {
var key = function (x) {return primer ? primer(x[field]) : x[field]};
return function (a,b) {
var A = key(a), B = key(b);
return ((A < B) ? -1 : (A > B) ? +1 : 0)) * [-1,1][+!!reverse];
}
}
there's an extra closing parenthesis on the line
return ((A < B) ? -1 : (A > B) ? +1 : 0))
should be
return ((A < B) ? -1 : (A > B) ? +1 : 0) ...etc
It would be useful if could provide the debugger error anyway. I exectued it in Chrome Developer Console and it gave the error:
SyntaxError: Unexpected token )
Which made it easy to find this broken line:
return ((A < B) ? -1 : (A > B) ? +1 : 0)) * [-1,1][+!!reverse];
You have unbalanced parenthesis. It should be:
return ((A < B) ? -1 : (A > B) ? +1 : 0) * [-1,1][+!!reverse];
There's one extra closing bracket here. Remove it.
return ((A < B) ? -1 : (A > B) ? +1 : 0)) * [-1,1][+!!reverse];
Also, semicolon everything.
var sort_by = function(field, reverse, primer) {
var key = function(x) {
return primer ? primer(x[field]) : x[field];
};
return function(a, b) {
var A = key(a), B = key(b);
return ((A < B) ? -1 : (A > B) ? +1 : 0) * [-1, 1][+!!reverse];
};
};

javascript sort array

My array isn't being sorted properly. Can someone let me know what I am doing wrong?
...
sortArray = new Array ("hello", "Link to Google", "zFile", "aFile");
//sort array
if (dir == "asc") {
sortArray.sort(function(a,b){return a - b});
} else {
sortArray.sort(function(a,b){return b - a});
}
for(var i=0; i<sortArray.length; i++) {
console.log(sortArray[i]);
}
the log is showing them in the same order as they were entered.
You want to make a comparison in your sort, not a subtraction:
if (dir == "asc") {
sortArray.sort(function(a, b) {
a = a.toLowerCase();
b = b.toLowerCase();
return a === b ? 0 : a > b : 1 : -1;
});
} else {
sortArray.sort(function(a, b) {
a = a.toLowerCase();
b = b.toLowerCase();
return b === a ? 0 : b > a : 1 : -1;
});
}
I also used toLowerCase() so that 'Link to Google' is placed appropriately.
EDIT: Updated to fix comparison issue according to comment.
See example →
You're trying to sort by subtracting strings, to which you'll get NaN.
The trouble is that "a - b" is treating the strings like numbers, which returns NaN. You will get the behavior you are looking for (assuming you are looking for case-sensitive sorts) if you replace your sorts with:
if (dir == "asc") {
sortArray.sort(function(a,b){return a < b ? -1 : 1});
} else {
sortArray.sort(function(a,b){return b < a ? -1 : 1});
}
Your comparator functions returns NaN, since it receives two strings, and performs subtraction, an operation that isn't well-defined on strings.
What you should have is something more like:
function(a,b){
return a>b? 1 : (a<b ? -1 : 0);
}
or you can use localeCompare:
function(a,b){
return a.localeCompare(b);
}
Remember to treat case appropriately, e.g. "L" < "a" whilst "l" > "a"

Categories

Resources