here is what I've tried
`
function sumAll(start, end) {
let average = Math.abs(start + end) / 2;
let numberOfTerms = Math.abs(end - start) / 1 + 1;
if (start >= 0 && end >= 0 ) {
return Math.abs(average * numberOfTerms);
} else if(typeof start === 'string' || typeof end === 'string'){
return "ERROR";
}else{
return "ERROR";
}
}
console.log("sumAll(10, '90') =" + sumAll(10, "90")); // I want this to return "ERROR" because "90" is String
console.log("sumAll(10, '90') =" + sumAll(10, "x"));// this works
`
but when I change input to "x" it works just fine. I think I miss something.
feel free to tell me anything, I'm a beginner. I'd love to learn new thing.
it is a great rule of thumb to do the validation first before anything else. because Javascript is a high level language, string that has only digit(s) in it like "1" or "100" or "123", Javascript will convert them into number automatically when you do comparison, subtraction, multiplication and division with other number or digit(s) only string. but not addition, because Javascript will concatenate the string instead.
function sumAll(start, end) {
if(typeof start !== "number" || typeof end !== "number") return "ERROR";
...
}
I want to loop through an array and check if each element is a number OR a string that could potentially turned into a number (e.g. "42"). If it can be "converted" then the element should be stored in a new array.
This is my code where I push all converted elements into a new array. Notice: I also want to count how many elements were "converted" from a string into a number and how many were not.
function numberConverter(arr) {
var converted = []
var counterConverted = 0
var counterNotConverted = 0
for (var c of arr) {
if (typeof c == "string" && Number(c) == "number") {
counterConverted++;
parseInt(c, 10);
converted.push(c)
} else {
counterNotConverted++
}
}
if (counterConverted == 0) {
return "no need for conversion"
} else {
return counterConverted + " were converted to numbers: " + converted + "; " + counterNotConverted + " couldn't be converted"
}
}
I know that my if condition
if(typeof c == "string" && Number(c) == "number")
is flawed logically, but I can't make up why.
Thanks for any hints and please explain it in beginner terms.
You can test if a string could be converted to a number like so:
val !== "" && Number.isNaN(Number(val)) === false
And the code could be written like so:
function numberConverter(arr) {
var converted = [];
var notconverted = [];
arr.forEach(function(val) {
if (typeof val === "number") {
converted.push(val);
} else if (typeof val === "string" && val !== "" && Number.isNaN(Number(val)) === false) {
converted.push(Number(val));
} else {
notconverted.push(val);
}
});
console.log("converted", converted);
console.log("not converted", notconverted);
}
numberConverter([0, "1", "", "123-foo", undefined, null, true, [], {}]);
The best solution is to use a functional approach to the code rather than an imperative one.
let arrayNumbers = ["Vadim", 99, {}, [], "100", "55AA", "AA55", Infinity, "false", true, null, -65.535, 2E1, "2E2"].filter( value => value !== null && value != Infinity && value !== '' && !isNaN(Number(value)) && !['boolean','array','object'].includes(typeof value)).map(value => +value);
console.log('Was Converted to Numbers:', arrayNumbers);
You need to check typeof string and isNaN in ESLint way (Number.isNaN(Number())).
function numberConverter(arr) {
const converted = [];
let counterConverted = 0;
for (let i = 0; i < arr.length; i += 1) {
const str = arr[i];
if (str && typeof str === 'string' && !Number.isNaN(Number(str))) {
const number = parseInt(str, 10);
converted.push(number);
counterConverted += 1;
}
}
const counterNotConverted = arr.length - converted.length;
if (counterConverted === 0) {
return 'No need for conversion.';
}
return `${counterConverted} were converted to numbers: ${converted.join(',')}; ${counterNotConverted} couldn't be converted`;
}
console.log(`'${numberConverter(['id', null, {}])}'`); // No need for conversion.
console.log(`'${numberConverter(['1', '-1', 'val'])}'`); // 2 were converted to numbers: [1,-1]; 1 couldn't be converted
console.log(`'${numberConverter(['1', '-1', '0', '1.5', 'val'])}'`); // 4 were converted to numbers: [1,-1,0,1]; 1 couldn't be converted
way to recursion to reduce string or array?
example case:
if we have. variable abcdfgh4zi output must be f4z
BECAUSE after d it must be e and then after h it must be I
it likes sorting...
I am trying it but failed using charCodeAt
function reduce(data) {
let result = ""
if (data.length <= 1) {
return result
} else if (data.charCodeAt(data[0])+1 !== data.charCodeAt(data[1])) {
result += data[0]
}
return result + reduce(data.slice(1))
}
console.log(reduce('abcdfgh4zi')); // f4z
the result is the same like that data, and if I am using it <, it gonna be empty string
if data "lmnop" the result is true and it gonna return empty string because they are sorting
and here to find the next alphabet I found on SO If chartCodeAt doesn't work
var abc = (parseInt(data[0], 36) + 1) % 36;
var nextAlphabet = ((!abc * 10 + abc).toString(36));
charCodeAt expects an index, you are giving it the character. So you are doing data.charCodeAt("a") + 1 !== data.charCodeAt("b")
You are also storing the first character, so you would be storing "d" and not "f"
function reduce(data) {
let result = ""
if (data.length <= 1) {
return result
} else if (data.charCodeAt(0)+1 !== data.charCodeAt(1)) {
result += data[1]
}
return result + reduce(data.slice(1))
}
console.log(reduce('abcdfgh4zi')); // f4z
I am trying to get the total seconds from 2 timestamps. I am currently getting the total days, hours and minutes, but I am trying to get all the way to the second. I am unable to find the formula...
Can someone point me in the right direction of getting the seconds too, along with the days, hours and minutes that I have already accomplished.
Here is my code thus far:
//gets timestamps
var clockedIn = "2017-03-02 09:45:25";
var clockedOut = "2017-03-04 09:49:06";
//sets timestamps to vars
var now = clockedIn;
var then = clockedOut;
var diff = moment.duration(moment(then).diff(moment(now)));
//parses out times
var days = parseInt(diff.asDays());
var hours = parseInt(diff.asHours());
hours = (hours - days * 24);
var minutes = parseInt(diff.asMinutes());
minutes = minutes - (days * 24 * 60 + hours * 60);
//I am looking to get seconds here...
Any help would be appreciated, even if it is just a link.
Thanks
One simple solution is to create two Date objects and get the difference between them.
var clockedIn = new Date("2017-03-02 09:45:25");
var clockedOut = new Date("2017-03-04 09:49:06");
var seconds = (clockedOut-clockedIn)/1000
// divide by 1000 because the difference we get will be in milliseconds.
Do you mean this function? seconds()
There's a nice plugin for momentjs available on github that makes this kind of formating very nice, as you can simply specify a format for your duration. https://github.com/jsmreese/moment-duration-format
var clockedIn = "2017-03-02 09:45:25";
var clockedOut = "2017-03-04 09:49:06";
//sets timestamps to vars
var now = clockedIn;
var then = clockedOut;
var diff = moment.duration(moment(then).diff(moment(now)));
console.log(diff.format("d [days], H [hours], m [minutes] [and] s [seconds] "));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment-with-locales.min.js"></script>
<script>
/*! Moment Duration Format v1.3.0
* https://github.com/jsmreese/moment-duration-format
* Date: 2014-07-15
*
* Duration format plugin function for the Moment.js library
* http://momentjs.com/
*
* Copyright 2014 John Madhavan-Reese
* Released under the MIT license
*/
(function (root, undefined) {
// repeatZero(qty)
// returns "0" repeated qty times
function repeatZero(qty) {
var result = "";
// exit early
// if qty is 0 or a negative number
// or doesn't coerce to an integer
qty = parseInt(qty, 10);
if (!qty || qty < 1) { return result; }
while (qty) {
result += "0";
qty -= 1;
}
return result;
}
// padZero(str, len [, isRight])
// pads a string with zeros up to a specified length
// will not pad a string if its length is aready
// greater than or equal to the specified length
// default output pads with zeros on the left
// set isRight to `true` to pad with zeros on the right
function padZero(str, len, isRight) {
if (str == null) { str = ""; }
str = "" + str;
return (isRight ? str : "") + repeatZero(len - str.length) + (isRight ? "" : str);
}
// isArray
function isArray(array) {
return Object.prototype.toString.call(array) === "[object Array]";
}
// isObject
function isObject(obj) {
return Object.prototype.toString.call(obj) === "[object Object]";
}
// findLast
function findLast(array, callback) {
var index = array.length;
while (index -= 1) {
if (callback(array[index])) { return array[index]; }
}
}
// find
function find(array, callback) {
var index = 0,
max = array.length,
match;
if (typeof callback !== "function") {
match = callback;
callback = function (item) {
return item === match;
};
}
while (index < max) {
if (callback(array[index])) { return array[index]; }
index += 1;
}
}
// each
function each(array, callback) {
var index = 0,
max = array.length;
if (!array || !max) { return; }
while (index < max) {
if (callback(array[index], index) === false) { return; }
index += 1;
}
}
// map
function map(array, callback) {
var index = 0,
max = array.length,
ret = [];
if (!array || !max) { return ret; }
while (index < max) {
ret[index] = callback(array[index], index);
index += 1;
}
return ret;
}
// pluck
function pluck(array, prop) {
return map(array, function (item) {
return item[prop];
});
}
// compact
function compact(array) {
var ret = [];
each(array, function (item) {
if (item) { ret.push(item); }
});
return ret;
}
// unique
function unique(array) {
var ret = [];
each(array, function (_a) {
if (!find(ret, _a)) { ret.push(_a); }
});
return ret;
}
// intersection
function intersection(a, b) {
var ret = [];
each(a, function (_a) {
each(b, function (_b) {
if (_a === _b) { ret.push(_a); }
});
});
return unique(ret);
}
// rest
function rest(array, callback) {
var ret = [];
each(array, function (item, index) {
if (!callback(item)) {
ret = array.slice(index);
return false;
}
});
return ret;
}
// initial
function initial(array, callback) {
var reversed = array.slice().reverse();
return rest(reversed, callback).reverse();
}
// extend
function extend(a, b) {
for (var key in b) {
if (b.hasOwnProperty(key)) { a[key] = b[key]; }
}
return a;
}
// define internal moment reference
var moment;
if (typeof require === "function") {
try { moment = require('moment'); }
catch (e) {}
}
if (!moment && root.moment) {
moment = root.moment;
}
if (!moment) {
throw "Moment Duration Format cannot find Moment.js";
}
// moment.duration.format([template] [, precision] [, settings])
moment.duration.fn.format = function () {
var tokenizer, tokens, types, typeMap, momentTypes, foundFirst, trimIndex,
args = [].slice.call(arguments),
settings = extend({}, this.format.defaults),
// keep a shadow copy of this moment for calculating remainders
remainder = moment.duration(this);
// add a reference to this duration object to the settings for use
// in a template function
settings.duration = this;
// parse arguments
each(args, function (arg) {
if (typeof arg === "string" || typeof arg === "function") {
settings.template = arg;
return;
}
if (typeof arg === "number") {
settings.precision = arg;
return;
}
if (isObject(arg)) {
extend(settings, arg);
}
});
// types
types = settings.types = (isArray(settings.types) ? settings.types : settings.types.split(" "));
// template
if (typeof settings.template === "function") {
settings.template = settings.template.apply(settings);
}
// tokenizer regexp
tokenizer = new RegExp(map(types, function (type) {
return settings[type].source;
}).join("|"), "g");
// token type map function
typeMap = function (token) {
return find(types, function (type) {
return settings[type].test(token);
});
};
// tokens array
tokens = map(settings.template.match(tokenizer), function (token, index) {
var type = typeMap(token),
length = token.length;
return {
index: index,
length: length,
// replace escaped tokens with the non-escaped token text
token: (type === "escape" ? token.replace(settings.escape, "$1") : token),
// ignore type on non-moment tokens
type: ((type === "escape" || type === "general") ? null : type)
// calculate base value for all moment tokens
//baseValue: ((type === "escape" || type === "general") ? null : this.as(type))
};
}, this);
// unique moment token types in the template (in order of descending magnitude)
momentTypes = intersection(types, unique(compact(pluck(tokens, "type"))));
// exit early if there are no momentTypes
if (!momentTypes.length) {
return pluck(tokens, "token").join("");
}
// calculate values for each token type in the template
each(momentTypes, function (momentType, index) {
var value, wholeValue, decimalValue, isLeast, isMost;
// calculate integer and decimal value portions
value = remainder.as(momentType);
wholeValue = (value > 0 ? Math.floor(value) : Math.ceil(value));
decimalValue = value - wholeValue;
// is this the least-significant moment token found?
isLeast = ((index + 1) === momentTypes.length);
// is this the most-significant moment token found?
isMost = (!index);
// update tokens array
// using this algorithm to not assume anything about
// the order or frequency of any tokens
each(tokens, function (token) {
if (token.type === momentType) {
extend(token, {
value: value,
wholeValue: wholeValue,
decimalValue: decimalValue,
isLeast: isLeast,
isMost: isMost
});
if (isMost) {
// note the length of the most-significant moment token:
// if it is greater than one and forceLength is not set, default forceLength to `true`
if (settings.forceLength == null && token.length > 1) {
settings.forceLength = true;
}
// rationale is this:
// if the template is "h:mm:ss" and the moment value is 5 minutes, the user-friendly output is "5:00", not "05:00"
// shouldn't pad the `minutes` token even though it has length of two
// if the template is "hh:mm:ss", the user clearly wanted everything padded so we should output "05:00"
// if the user wanted the full padded output, they can set `{ trim: false }` to get "00:05:00"
}
}
});
// update remainder
remainder.subtract(wholeValue, momentType);
});
// trim tokens array
if (settings.trim) {
tokens = (settings.trim === "left" ? rest : initial)(tokens, function (token) {
// return `true` if:
// the token is not the least moment token (don't trim the least moment token)
// the token is a moment token that does not have a value (don't trim moment tokens that have a whole value)
return !(token.isLeast || (token.type != null && token.wholeValue));
});
}
// build output
// the first moment token can have special handling
foundFirst = false;
// run the map in reverse order if trimming from the right
if (settings.trim === "right") {
tokens.reverse();
}
tokens = map(tokens, function (token) {
var val,
decVal;
if (!token.type) {
// if it is not a moment token, use the token as its own value
return token.token;
}
// apply negative precision formatting to the least-significant moment token
if (token.isLeast && (settings.precision < 0)) {
val = (Math.floor(token.wholeValue * Math.pow(10, settings.precision)) * Math.pow(10, -settings.precision)).toString();
} else {
val = token.wholeValue.toString();
}
// remove negative sign from the beginning
val = val.replace(/^\-/, "");
// apply token length formatting
// special handling for the first moment token that is not the most significant in a trimmed template
if (token.length > 1 && (foundFirst || token.isMost || settings.forceLength)) {
val = padZero(val, token.length);
}
// add decimal value if precision > 0
if (token.isLeast && (settings.precision > 0)) {
decVal = token.decimalValue.toString().replace(/^\-/, "").split(/\.|e\-/);
switch (decVal.length) {
case 1:
val += "." + padZero(decVal[0], settings.precision, true).slice(0, settings.precision);
break;
case 2:
val += "." + padZero(decVal[1], settings.precision, true).slice(0, settings.precision);
break;
case 3:
val += "." + padZero(repeatZero((+decVal[2]) - 1) + (decVal[0] || "0") + decVal[1], settings.precision, true).slice(0, settings.precision);
break;
default:
throw "Moment Duration Format: unable to parse token decimal value.";
}
}
// add a negative sign if the value is negative and token is most significant
if (token.isMost && token.value < 0) {
val = "-" + val;
}
foundFirst = true;
return val;
});
// undo the reverse if trimming from the right
if (settings.trim === "right") {
tokens.reverse();
}
return tokens.join("");
};
moment.duration.fn.format.defaults = {
// token definitions
escape: /\[(.+?)\]/,
years: /[Yy]+/,
months: /M+/,
weeks: /[Ww]+/,
days: /[Dd]+/,
hours: /[Hh]+/,
minutes: /m+/,
seconds: /s+/,
milliseconds: /S+/,
general: /.+?/,
// token type names
// in order of descending magnitude
// can be a space-separated token name list or an array of token names
types: "escape years months weeks days hours minutes seconds milliseconds general",
// format options
// trim
// "left" - template tokens are trimmed from the left until the first moment token that has a value >= 1
// "right" - template tokens are trimmed from the right until the first moment token that has a value >= 1
// (the final moment token is not trimmed, regardless of value)
// `false` - template tokens are not trimmed
trim: "left",
// precision
// number of decimal digits to include after (to the right of) the decimal point (positive integer)
// or the number of digits to truncate to 0 before (to the left of) the decimal point (negative integer)
precision: 0,
// force first moment token with a value to render at full length even when template is trimmed and first moment token has length of 1
forceLength: null,
// template used to format duration
// may be a function or a string
// template functions are executed with the `this` binding of the settings object
// so that template strings may be dynamically generated based on the duration object
// (accessible via `this.duration`)
// or any of the other settings
template: function () {
var types = this.types,
dur = this.duration,
lastType = findLast(types, function (type) {
return dur._data[type];
});
// default template strings for each duration dimension type
switch (lastType) {
case "seconds":
return "h:mm:ss";
case "minutes":
return "d[d] h:mm";
case "hours":
return "d[d] h[h]";
case "days":
return "M[m] d[d]";
case "weeks":
return "y[y] w[w]";
case "months":
return "y[y] M[m]";
case "years":
return "y[y]";
default:
return "y[y] M[m] d[d] h:mm:ss";
}
}
};
})(this);
</script>
You don't have to use any complex method to calculate the difference of the two moment (or Date) objects. Simply calculating the difference gives you the total difference between the two dates in milliseconds.
var now = moment();
var then = moment().add(1231, 'second'); // just to have an example different date
var milliseconds = +then - +now;
var seconds = milliseconds / 1000;
var minutes = seconds / 60;
var hours = minutes / 60;
If you would like to get the difference formatted like HH:mm:ss, just convert the diff milliseconds back to moment object and use .format():
var now = moment();
var then = moment().add(1231, 'second'); // just to have an example different date
var diff_m = moment(+then - +now);
console.log(diff_m.format('HH:mm:ss'));
a script returns either a number like 0.0580 so in x.xxxx format or a (x) for X units left.
I want to format the number 0.0580 and return 5.8 cent or return x units left.
Any ideas how to do that in javascript? Especially how do I format the x.xxxx?
In case the first x is not 0 I want to return e.g. 1.75$.
MS has written a nice plugin for jquery. it's especially useful if you're localizing. Give it a go:
http://weblogs.asp.net/scottgu/archive/2010/06/10/jquery-globalization-plugin-from-microsoft.aspx
I'm not sure if this can be used outside of jquery...
I may be spoiling you here, but whatever. Here's a function that I found somewhere at some point and have been recycling since. I haven't actually bothered to look much into it to figure out what it does exactly, but it has been rather useful:
function FormatMoneyAmount(starting_string, ending_string) {
//check validity of input (true = invalid, false = valid)
var valid_exp = new RegExp ('[^0-9,.$]', 'gi');
input_invalid = (typeof(ending_string) == 'undefined' && valid_exp.test(starting_string));
//check if more than 2 digits follow decimal or no decimal
decimal_invalid = typeof(ending_string) == 'undefined' && (starting_string.indexOf('.') > -1) && ((starting_string.length - starting_string.indexOf('.')) > 3);
if (input_invalid || decimal_invalid) {
ending_string = starting_string;
} else {
//remove commas, dollar signs
var replace_exp = new RegExp ('[,$]', 'gi');
starting_string = starting_string.replace(replace_exp, '');
//remove decimal if ending string not set, save for adding on later
var decimal_substring = '';
if (typeof(ending_string) == 'undefined' && starting_string.indexOf('.') > -1) {
decimal_substring = starting_string.substring(starting_string.indexOf('.'), starting_string.length);
remaining_string = starting_string.substring(0,starting_string.indexOf('.'));
} else {
remaining_string = starting_string;
}
//if string is already 3 characters or less, do nothing
if (remaining_string.length > 3) {
//separate last 3 characters of string from rest of string
var final_three = remaining_string.substring(remaining_string.length - 3, remaining_string.length);
remaining_string = remaining_string.substring(0, remaining_string.length - 3);
//if not first group of 3, add new group before old group with comma, else set to new group
ending_string = (typeof(ending_string) == 'undefined') ? final_three + ((typeof(decimal_substring) == 'undefined') ? '' : decimal_substring) : final_three + ',' + ending_string;
//call function again if more than 3 digits remaining to process, else add to end string
if (remaining_string.length > 3) {
ending_string = FormatMoneyAmount(remaining_string, ending_string);
} else {
ending_string = remaining_string + ',' + ending_string;
}
} else {
ending_string = (typeof(ending_string) == 'undefined') ? remaining_string : remaining_string + ',' + ending_string + ((typeof(decimal_substring) == 'undefined') ? '' : decimal_substring);
}
}
return ending_string;
}
The first thing to do is check the format of the string, since you will have two code paths depending on the result:
if (typeof num = "string" && num.slice(0,1) == "(" && num.slice(-1) == ")") {
// String is in the format (x), so we just need to return that number
return num.slice(1,-1) + " units left";
}
The next part is to check if the number is less than 1, indicating that it is cents and not whole dollars. If it is less than 1, multiplying it by 100 will give you the number of cents you're after:
if (+num < 1)
// 0.0580 * 100 = 5.8
return (num * 100) + " cents";
else
return +num + "$";