I have parseNotAvailable function that based on version have some logic, so i have penalties that has coming as version 2 but i need to have logic same as version 1, So i tried to pass as null to get 0 but its not working and throwing error.
Any better approach to achieve above task ?
main.js
let newPrice = {
copayEmployer: parseNotAvailable('N/A', 1),
penalties: parseNotAvailable('N/A', null),
secondaryClaimNumber: parseNotAvailable('N/A',2)
};
function parseNotAvailable(value, version) {
if ((value === 'N/A' || value === 'n/a') && (version || version === 1)) {
return 0;
} else if ((value === 'N/A' || value === 'n/a') && version === 2) {
return null;
} else {
return parseFloat(value);
}
};
// console.log(parseNotAvailable('N/A', 1));
console.log(newPrice);
expected Result
{ copayEmployer: 0, penalties: 0, secondaryClaimNumber: null }
with above code its returning
{ copayEmployer: 0, penalties: NaN, secondaryClaimNumber: 0 }
In parseNotAvailable('N/A', null) version is null and does not pass if statements na goes to else statement return parseFloat(value);
In parseNotAvailable('N/A', 2) version is 2 and it pass first if statements... ||(value || value === 1) and return 0;
You have wrong assertion if ((value === 'N/A' || value === 'n/a') && (version || version === 1)) it should be if ((value === 'N/A' || value === 'n/a') && (!version || version === 1))
You're code is flowing to the else block and trying attempting to parseInt('N/A'), which obviously is NaN. You may want to rethink your conditions there. I added a simple isNaN check to your code as you can see:
try {
let newPrice = {
copayEmployer: parseNotAvailable('N/A', 1),
penalties: parseNotAvailable('N/A', null),
secondaryClaimNumber: parseNotAvailable('N/A', 2)
};
console.log(newPrice);
} catch (err) {
console.error(err)
}
function parseNotAvailable(value, version) {
if ((value === 'N/A' || value === 'n/a') && (version || version === 1)) {
return 0;
} else if ((value === 'N/A' || value === 'n/a') && version === 2) {
return null;
} else {
//Do a check here for NaN value - this probably isnt needed if you straigten out your flow control conditions
if (isNaN(value)) {
throw `${value} is NaN`;
}
return parseFloat(value);
}
};
Related
as an exercise, I am trying to find the most efficient way to refactor this if...if statement.
This is the original code:
interface Validatable {
value: string | number;
required?: boolean;
minLength?: number;
maxLength?: number;
min?: number;
max?: number;
}
function validate(validatableInput: Validatable) {
let isValid = true;
if (validatableInput.required) {
isValid = isValid && validatableInput.value.toString().trim().length !== 0;
}
if (
validatableInput.minLength != null &&
typeof validatableInput.value === 'string'
) {
isValid =
isValid && validatableInput.value.length >= validatableInput.minLength;
}
if (
validatableInput.maxLength != null &&
typeof validatableInput.value === 'string'
) {
isValid =
isValid && validatableInput.value.length <= validatableInput.maxLength;
}
if (
validatableInput.min != null &&
typeof validatableInput.value === 'number'
) {
isValid = isValid && validatableInput.value >= validatableInput.min;
}
if (
validatableInput.max != null &&
typeof validatableInput.value === 'number'
) {
isValid = isValid && validatableInput.value <= validatableInput.max;
}
return isValid;
}
and this is what I achieved so far:
function validate(validatableInput: Validatable) {
const { required, minLength, maxLength, min, max } = validatableInput; // This methos extracts the properties from the object
const validatableInputValue = validatableInput.value;
let isValid = true;
if (required) {
isValid = isValid && validatableInputValue.toString().trim().length !== 0;
}
if (minLength != null && typeof validatableInputValue === "string") {
isValid = isValid && validatableInputValue.length >= minLength;
}
if (maxLength != null && typeof validatableInputValue === "string") {
isValid = isValid && validatableInputValue.length <= maxLength;
}
if (min != null && typeof validatableInputValue === "number") {
isValid = isValid && validatableInputValue >= min;
}
if (max != null && typeof validatableInputValue === "number") {
isValid = isValid && validatableInputValue <= max;
}
return isValid;
}
Is there anything else I could do? Like use a switch statement instead, or something else? Thank you!
All of the conditions follow a pattern: if a particular prerequisite is fulfilled, then validate the input value against something. You can exploit this by creating an array of such conditions: each item can have a prerequisite (eg required) and a test (eg value.toString().trim().length !== 0). Then iterate over the array with something like .every to check that each truthy prerequisite has its corresponding condition fulfilled.
function validate(validatableInput: Validatable) {
const { required, minLength, maxLength, min, max, value } = validatableInput;
const isStr = typeof value === "string";
const isNum = typeof value === "number";
const conditions = [
[required, value.toString().trim().length !== 0],
[minLength != null && isStr, value.length >= minLength],
[maxLength != null && isStr, value.length <= maxLength],
[min != null && isNum, value >= min],
[max != null && isNum, value <= max],
];
return conditions.every(([prereq, result]) => result || !prereq);
}
As another approach that keeps the existing structure:
function validate(validatableInput: Validatable) {
const { value, required, minLength, maxLength, min, max } = validatableInput;
if (required && value.toString().trim().length === 0) {
return false;
}
if (typeof value !== "string" || typeof value !== "number") {
return true
}
if (typeof value === "string") {
if (minLength && value.length < minLength) {
return false;
}
if (maxLength && value.length > maxLength) {
return false;
}
}
if (min && value < min) {
return false;
}
if (max && value > max) {
return false;
}
return true;
}
A few things of note:
Some people have problems with early returns; I don't--it's immediately clear while reading what happens without having to continue reading the function.
It's not as elegant as the every option, but it allows for easier modification, logging, etc. because it's very explicit and blocked out.
Since Validatable is a type I'm not sure why this functionality wants to be pulled out of it, particularly since decisions are being made based on type information of a Validatable property.
<!doctype html>
<html>
<script>
function isNumber(value) {
return typeof (value) != "boolean" && !isNaN(value) && value.length > 0;
}
function minMaxDefrost(value, min, max) {
if (value.length == 0 || value == "-") return value;
if (!isNumber(value)) return value.substring(0, value.length - 1);
console.log("minMaxDefrost called ")
if (parseFloat(value) < min){
return min;
}
else if (parseFloat(value) > max){
return max;
}
else {
return Math.floor(value);
}
}
minMaxDefrost(4, 0, 12);
</script>
</html>
I use this function in a html keyup function and it works fine but when i try to call it by itself at the start of the code i get the error message Uncaught TypeError: value.substring is not a function
also not when i call this function from the keyup i use "this.value = minMaxDefrost(this.value, -80, 150, 0)
im assuming the error has got to do with the this.value but i dont know how to fix it
isNumber doesn't exactly do its job as Mark Hanna suggests.. a better isNumber would be something like
function isNumber(num){
let num1=num-0, num2=num-1
return num2!=num1 && !!(num2||num1) && typeof(num)!="object"
//Infinity would fail the test num2!=num1
//Normal non-numbers would fail !!(num2||num1)
//null would fail typeof(null)!="object"
//However, 0, and even "0" will pass this test
}
Here is it returned in the code you gave us
function isNumber(num){
let num1=num-0, num2=num-1
return num2!=num1 && !!(num2||num1) && typeof(num)!="object"
//Infinity would fail the test num2!=num1
//Normal non-numbers would fail !!(num2||num1)
//null would fail typeof(null)!="object"
//However, 0, and even "0" will pass this test
}
function minMaxDefrost(value, min, max) {
if (value.length == 0 || value == "-") return value;
if (!isNumber(value)) return value.substring(0, value.length - 1);
console.log("minMaxDefrost called ")
if (parseFloat(value) < min){
return min;
}
else if (parseFloat(value) > max){
return max;
}
else {
return Math.floor(value);
}
}
minMaxDefrost(4, 0, 12);
isNumber(4) evaluates to false, so you're trying to call a substring method on 4 but that doesn't exist. Use typeof value === 'number' instead to test if something is a number. Or better yet, use typeof value === 'string' before treating it like it's definitely a string.
I am working on calendar with js in my project for availabilities it works correctly. but when I have a record which has a start date equal an end date.
for add event to my calendar i'm using this push:
listDate.push({startDate :strDate, endDate : enDate});
in my script datetimepicker this is function isAvailable
isAvailable: function(date, month, year) {
for (var i in this.unavailable) {
var book_date = this.unavailable[i].startDate.split("-");
if (book_date.length !== 3) {
return false;
} else if (
(book_date[0] == "*" || book_date[0] - year === 0) &&
(book_date[1] == "*" || book_date[1] - month === 0) &&
(book_date[2] == "*" || book_date[2] - date === 0)
) {
return false;
}
}
return true;
}
I get this issues: Cannot read property 'split' of undefined in this line
var book_date = this.unavailable[i].startDate.split("-");
please any help thanks for you
this.unavailable[i].startDate is undefined. Does listDate reference this.unavailable or is it a different array? Put a breakpoint or use console.log to inspect the contents of this.unavailable in the isAvailable function.
The code does not give me any error in my console. Can you try storing the value of unavailable in a separate variable and use that variable instead. This might help.
isAvailable: function(date, month, year) {
var unavailable = this.unavailable;
for (var i in unavailable) {
var book_date = unavailable[i].startDate.split("-");
if (book_date.length !== 3) {
return false;
} else if (
(book_date[0] == "*" || book_date[0] - year === 0) &&
(book_date[1] == "*" || book_date[1] - month === 0) &&
(book_date[2] == "*" || book_date[2] - date === 0)
) {
return false;
}
}
return true;
}
You are using a for in loop to iterate through an array - for in loops should only be used on objects. You should use a plain for loop or forEach
isAvailable: function(date, month, year) {
for (var i = 0; i < this.unavailable.length; i++) {
var book_date = this.unavailable[i].startDate.split("-");
if (book_date.length !== 3) {
return false;
} else if (
(book_date[0] == "*" || book_date[0] - year === 0) &&
(book_date[1] == "*" || book_date[1] - month === 0) &&
(book_date[2] == "*" || book_date[2] - date === 0)
) {
return false;
}
}
return true;
}
Ive been doing the 'Numerical Palindrome #1' Kata in codewars and I feel like this code should work, but its saying that palindrome(1221) is coming back as false - when obviously it should be coming back as true. if anyone can see why this would be happening i would greatly appreciate it! the challenge said that if num was less than 0, or wasnt an integer then it should return 'not valid'.
function palindrome(num) {
if(typeof num == 'number'){
if(Number.isInteger(num) && num>=0){
return(toString(num) === toString(num).split('').reverse().join(''));
}
else{return 'Not valid';
}
}
else { return 'Not valid';
}
}
toString is a method of Number.prototype so you call it from the number:
function palindrome(num) {
if (typeof num == 'number') {
if (Number.isInteger(num) && num >= 0) {
return (num.toString() === num.toString().split('').reverse().join(''));
} else {
return 'Not valid';
}
} else {
return 'Not valid';
}
}
console.log(palindrome(500))
console.log(palindrome(505))
There was some problem with your code.
you need to use toString() like below :
num.toString()
and also you don't need two if for checking your conditions, you can do it with only 1 if.
I update your code :
var a = function palindrome(num) {
if(typeof num == 'number' && Number.isInteger(num) && num>=0)
return(num.toString() === num.toString().split('').reverse().join(''));
else
return 'Not valid';
}
console.log(a(1001));
https://jsfiddle.net/emilvr/qkz5ypq9/
toString method that you are using will return toString(123456) = "[object Undefined]" . & toString(123456).split('').reverse().join('') = "]denifednU tcejbo[" and hence it is failing. to convert a number to string best is to concatenate it with "", like 12345+"";
You should use String instead of toString.
function palindrome(num) {
if (typeof num == 'number' && Number.isInteger(num) && num >= 0) {
return (String(num) === String(num).split('').reverse().join(''));
}
return 'Not valid';
}
I'm attempting to write a filter for use in a grid that will catch all null, undefined, blank string, or other similar values and display a dash "-". I've written the following so far, but it doesn't catch null values, and I'm wondering if it could be more succinct and possibly refactored to avoid three layers of nested if/else statements. Percentage values need to be checked that they're over 0 and under 1. Also, negative numbers and 0's should be returned as is. Thanks!
angular.module('AdverseEventsExplorer.main').filter('emptyCellFilter', function ($filter) {
return function (input, cellFilter, args1, args2) {
if (cellFilter == undefined) {
return (angular.isNumber(input) || angular.isDefined(input) && input.length > 0) ? input : '-';
} else {
if (cellFilter.match(/pctg|percent|pctgFilter|incidence/ig)) {
return (input > 0 && input < 1.0000000) ? $filter(cellFilter)(input, args1, args2) : '-';
} else {
return (angular.isNumber(input) || angular.isDefined(input) && input.length > 0) ? input : '-';
}
}
};
});
Version 2.0 taking into account #tymeJV's comment:
angular.module('AdverseEventsExplorer.main').filter('emptyCellFilter', function ($filter) {
return function (input, cellFilter, args1, args2) {
if (!cellFilter) {
return (angular.isNumber(input) || (input)) ? input : '-';
} else {
if (cellFilter.match(/pctg|percent|pctgFilter|incidence/ig)) {
return (input > 0 && input < 1.0000000) ? $filter(cellFilter)(input, args1, args2) : '-';
} else {
return (angular.isNumber(input) || (input)) ? $filter(cellFilter)(input, args1, args2) : '-';
}
}
};
});
Whenever you encounter a function that's getting too complex to refactor try extracting some of the smaller statements to concisely named variables. It makes it much easier for our brains to keep track of the function's requirements, and it's also more readable to new devs reading your code.
var inputHasValue = angular.isNumber(input) || input;
if(!inputHasValue){
return '-';
}
if (!cellFilter) {
return input;
}
var isPercentageCell = cellFilter.match(/pctg|percent|pctgFilter|incidence/ig);
var valueIsInRange = input > 0 && input < 1;
if(!isPercentageCell || valueIsInRange){
return $filter(cellFilter)(input, args1, args2);
}
return '-';
typeof x ==='number' || !!x
is false when x is null, undefined or empty string
Only one case in which it doesn't work – if you need to filter boolean variables, but your case doesn't seem to need it.
Anyway in that case you can use
typeof x === 'boolean' || typeof x ==='number' || !!x