adding values that could contain a null/undefined value - javascript

I'm sorry to ask, but I just can't find the info.
My script needs to add 12 items together but some of them may have null/undefined values
ie
1 + null + 3 + 4 + null + null + 7
How do I add these together?
$scope.wepweight = ($scope.selectedWeapon1Ship1.Vars.weight) +($scope.selectedWeapon2Ship1.Vars.weight)
At the moment, the values will add together once all the ng-models are populated (because of the null/undefined values), but I need to keep a running total.
https://jsfiddle.net/wayneker/3u6ob98d/2/
(search for "//calculate weight for hull" within the JS section to see the relevant section of code)

You could take the Nullish coalescing operator ?? which checks if the value is null or undefined, then it takes the right hand side value.
const sum = 1 + (null ?? 0) + 2 + (undefined ?? 0);
console.log(sum);

You can use the || operator to check if the value is null or undefined, and if it is, add 0 to it:
console.log(1 + (null || 0) + 3 + 4 + (undefined || 0) + 7) // 15

You didn't specify where you got your values from, but either they are stored in an array or you can put them in an array.
Once you have them in an array, it's elegant with reduce:
// assuming weight is your array
weight.reduce((a,b) => typeof b === 'number' ? a + b : a, 0);
What this code does is that it starts with 0 and adds every element that is a number (which null is not)

i think this one can help you
$scope.wepweight = calcSumValue();
function calcSumValue() {
let ans = 0;
for(let i = 1; i <= 12; i++) {
const value = $scope[`selectedWeapon${i}Ship1`].Vars.weight
if (value)
ans += value;
}
return ans;
}

Related

How can I make this for loop iteration available inside the function for the if( condition ) with out repeating the function outcome n times as i?

I have a function which requires an Array iteration in order to set proper conditionals in the if statement, here's the code:
const code = reactive([] as string[])
for (let field = 0; field < props.length; field++) code.push('')
const inputs = reactive([] as HTMLInputElement[])
const focusOn = ref(0 as number | null)
onMounted(() => {
inputs[0].focus()
})
const nextInput = (): void => {
for (let i = 0; i < code.length; i++) {
console.log(code[i])
console.log(code)
if (
focusOn.value !== null &&
focusOn.value < props.length - 1 &&
code[i] !== ' ' &&
code[i] !== undefined
) {
inputs[focusOn.value + 1].focus()
}
}
}
You can ignore the console.log.
the problem I'm having is that the outcome ⇒ inputs[i + 1] is not
working as expected ⇒ stepping to the next input by 1, instead is
doing something like inputs[i +1] * 4 in every click ⇒ I assume it's
the number of iterations which by the way is 4, that's the
code.length.
focusOn.value ⇒ index number
What I'm trying to achieve is to iterate the code object[] in order to use its outcome as conditionals, but not to have it in the same scope as the return, so I can avoid returning the result x times as iterations.
I already tried numerous things, but I'm having an understanding level problem here. How can I solve this? Any help/suggestion is greatly appreciated!
btw, I just added more code to give you context that was clearly missing, my bad.

How to set value in array depending on previous value of array

I've got a simple problem, but I'm struggling to find the easiest solution without transforming the array a hundred times.
I want to do a simple stacked graph in google sheets, with weeks on X and values on Y. I got the values for each week, but only for weeks, that have a value.
The values are all calculations I've done with google apps script/ js.
person1 = [[2019/37,2], [2019/42,3]] and so on, for multiple persons and for 80 weeks in total.
The num value is the total value after each week. So I want the array to be filled up with the missing weeks. Therefore I mapped this to another array, where I have all the weeks but no values, giving these weeks the value 0:
person1= [[2019/37,2],[2019/38,0],[2019/39,0],...,[2019/42,3],[2019/43,0],[2019/44,0],...]
This of course does not fit to see a progress in the graph.
So I need something to set the weeks, which were filled up, to the previous value, resulting in
person1= [[2019/37,2],[2019/38,2],[2019/39,2],...,[2019/42,3],[2019/43,3],[2019/44,3],...]
Looping through this and setting the values with something like person[i][1] == person[i-1][1] seems not to be a good practice of course.
So, what would be the best way to achieve this? I'm kind of stuck with this now, I feel like I don't see the forest for the trees.
Thanks in advance!
code:
let valueArray = [[2019/37,2], [2019/42,3]]
let weeksArray = [2019/38,2019/39,2019/40,2019/41...]
//find missing weeks
let notFound = weeksArray.filter(el => valueArray.includes(el) == false).map(x => [x,0]);
//concat and sort
let outArray = arr.concat(notFound).sort((a,b)=> a[0].localeCompare(b[0]));
//output:
//[[2019/37,2],[2019/38,0],[2019/39,0],...,[2019/42,3],[2019/43,0],[2019/44,0],...]
Solution:
Since you already have the expanded array, you can use map on the whole array and use a function to replace the values:
var weeks = [[2019/37,2],[2019/38,0],[2019/39,0],[2019/40,3],[2019/41,0],[2019/42,4],[2019/43,0],[2019/44,0]];
weeks.map((a,b)=>{weeks[b][1] = (a[1] == 0 && b > 0) ? weeks[b-1][1] : weeks[b][1]});
To make it more readable, this is the same as:
weeks.forEach(function missing(item,index,arr) {
if (item[1] == 0 && index > 0) {
arr[index][1] = arr[index-1][1];
}
}
);
Console log:
References:
Arrow Functions
Conditional Operator
Array.prototype.map()
function fixArray() {
var array = [["2019/1", "1"], ["2019/10", "2"], ["2019/20", "3"], ["2019/30", "4"], ["2019/40", "5"]];
var oA = [];
array.forEach(function (r, i) {
oA.push(r);
let t1 = r[0].split('/');
let diff;
if (i + 1 < array.length) {
let inc = 1;
let t2 = array[i + 1][0].split('/');
if (t1[0] == t2[0] && t2[1] - t1[1] > 1) {
do {
let t3 = ['', ''];
t3[0] = t1[0] + '/' + Number(parseInt(t1[1]) + inc);
t3[1] = r[1];
diff = t2[1] - t1[1] - inc;
oA.push(t3);
inc++;
} while (diff > 1);
}
}
});
let end = "is near";
console.log(JSON.stringify(oA));
}
console.log:
[["2019/1","1"],["2019/2","1"],["2019/3","1"],["2019/4","1"],["2019/5","1"],["2019/6","1"],["2019/7","1"],["2019/8","1"],["2019/9","1"],["2019/10","2"],["2019/11","2"],["2019/12","2"],["2019/13","2"],["2019/14","2"],["2019/15","2"],["2019/16","2"],["2019/17","2"],["2019/18","2"],["2019/19","2"],["2019/20","3"],["2019/21","3"],["2019/22","3"],["2019/23","3"],["2019/24","3"],["2019/25","3"],["2019/26","3"],["2019/27","3"],["2019/28","3"],["2019/29","3"],["2019/30","4"],["2019/31","4"],["2019/32","4"],["2019/33","4"],["2019/34","4"],["2019/35","4"],["2019/36","4"],["2019/37","4"],["2019/38","4"],["2019/39","4"],["2019/40","5"]]

Typescript : Trying the addition of two variables but get the concatenation of the two

I have three variable in my Typescript class :
A:number;
B:number;
C:number;
in another part of the class i try to make the addition of the two variable A and B :
this.C = this.A+this.B; // A =20 and B = 50;
and I display C in the html template
<span>{{C}}</span>
My problem is, instead of getting the addition of the TWO variable (20+50=70) i get the concatenation (2050)!!
Can someone help me please ?
UPDATE :
Here is the exact code portion that cause problem :
goTo(page:number,type:script) {
//
this.pageFirstLineNumber = page;
this.pageLastLineNumber = page + this.LINE_OFFSET; //concatenation!!
}
Notice that pageLastNumber is declared as number type, LINE_OFFSET is olso number type, i have found a solution to this issue but the typescript compiler output an error (forbidden eval):
////
....
this.pageFirstLineNumber = eval(page.toString()); // now It works !!
this.pageLastLineNumber = page + this.LINE_OFFSET; //concatenation!!
UPDATE
Here is the declaration of the LINE_OFFSET variable :
private _calculateOffset(fontSize: number) {
let linesDiff = (fontSize * 27) / 14;
let lines:number = 27 - (linesDiff - 27);
this.LINE_OFFSET = Math.floor(lines);
if (fontSize >= 17 && fontSize <= 20) {
this.LINE_OFFSET += (Math.floor(fontSize / 3) - 2);
}
if (fontSize > 20 && fontSize <= 23) {
this.LINE_OFFSET += (Math.floor(fontSize / 2) - 2);
}
if (fontSize > 23 && fontSize <= 25) {
this.LINE_OFFSET += (Math.floor(fontSize / 2));}
if (fontSize > 25 && fontSize <= 27) {
this.LINE_OFFSET += (Math.floor(fontSize / 2) + 1);
}
if (fontSize > 27 && fontSize <= 30) {
this.LINE_OFFSET += (Math.floor(fontSize / 2) + 4);
}
}
prepend the numbers with +:
let a = +b + +c;
ref
When you declare in an interface that a property is a number then it stays as a declaration only, it won't be translated into javascript.
For example:
interface Response {
a: number;
b: number;
}
let jsonString = '{"a":"1","b":"2"}';
let response1 = JSON.parse(jsonString) as Response;
console.log(typeof response1.a); // string
console.log(typeof response1.b); // string
console.log(response1.a + response1.b); // 12
As you can see, the json has the a and b as strings and not as numbers and declaring them as numbers in the interface has no effect on the runtime result.
If what you get from your server is encoded as strings instead of numbers then you'll need to convert them, for example:
let response2 = {
a: Number(response1.a),
b: Number(response1.b)
} as Response;
console.log(typeof response2.a); // number
console.log(typeof response2.b); // number
console.log(response2.a + response2.b); // 3
(entire code in playground)
Problem is variable typecasting not done.
You need to do in following way.
A : parseInt(number);
B : parseInt(number);
then you will get sum C= A+b instead of concatenation.
I ran into similar problem , was able to solve as below :
C:number =0;
A:number=12;
B:number=0.4;
C= Number.parseInt(A.toString()) + Number.parseFloat(B.toString());
console.log("C=" + C );
seems stupid , to convert a number to string and parse again to number , but this is how I solved my problem.
Finnaly i find what cause the error, i get the page variable from the html template (its an input value), it is defined as number type in the function parameter, but in reality is a string and typescript cant check the type of variable from html template, so when a try parseInt(page) static typping highlight an error ! i have soved the issue by giving the page variable an "" type, then applying parseInt to the page variable.
That means there are string values in either A or B variables. Check your code for unsafe parts, I mean casting to <any>, and casting server responses to interfaces. That could cause to have string values in number variables.
const value = Number(stringOrNum)+1;

Check if Javascript Array Values are Sequential and Not Equal

I read this, but it doesn't apply (and/or, I can't figure out how to adapt the solutions). I also found this, but I don't want to change the array - I just want to check the information. I was unable to adapt the solutions to fit my needs.
I want to find out of the values in a Javascript Array are Sequential.
For example - I have an array of UNIX timestamps
var ts = [1451772000, 1451858400, 1452031200]
I want to return true if they are sequential (lower to higher values) and false if they are not sequential. I would also like to return false if there are duplicate values.
You can use Array.prototype.every, like this
var data = [1451772000, 1451858400, 1452031200];
console.log(data.every((num, i) => i === data.length - 1 || num < data[i + 1]));
The same can be written with a normal function, like this
console.log(data.every(function(num, index) {
return index === data.length - 1 || num < data[index + 1];
}));
There are basically only two conditions to take care here
If we reached the last index, then all the elements are good.
If it is not the last element, then the current number should be strictly lesser than the next element.
This expression takes care of the above two conditions.
i === data.length - 1 || num < data[i + 1]
The every function calls the function passed to it, for each and every value of the array, with three parameters.
current element,
current index
the actual array
It will keep calling the function, till the array elements run out or any of the calls to the function returns a falsy value.
You can use simple for-loop like this
function isSequential(data) {
for (var i = 1, len = data.length; i < len; i++) {
// check if current value smaller than previous value
if (data[i] < data[i - 1]) {
return false;
}
}
return true;
}
console.log(isSequential([1]));
console.log(isSequential([1, 2, 3, 4]));
console.log(isSequential([1, 5, 3, 4]));
console.log(isSequential([1451772000, 1451858400, 1452031200]));
This works on any length and prevents the first element to check.
function isSequential(array) {
return array.every(function (a, i, aa) {
return !i || aa[i - 1] < a;
});
}
document.write(isSequential([42]) + '<br>');
document.write(isSequential([1, 2, 3, 4]) + '<br>');
document.write(isSequential([1, 5, 3, 4]) + '<br>');
document.write(isSequential([1451772000, 1451858400, 1452031200]) + '<br>');

JS concatenating object property values (numeric) instead of adding

In an intersect function, that checks if two objects intersect on the canvas, I need to add the obj.x and obj.width property to get the obj.right(side). Somehow the properties are concatenated instead of added. It probably has something to do with reference-type but I don't see how I can capture the values in primitive types.
function intersects(obj1, obj2) { // checks if 2 shapes intersect
var ob2x = obj2.x;
var ob2width = obj2.width;
if (obj1.x > +obj2.x + 70 || obj2.x > +obj1.x + 70) {
console.log('false : obj1.x=' + obj1.x + ' obj2.right=' + parseInt(ob2x) + parseInt(ob2width));
return false;
}
if (obj1.y > +obj2.y + +obj2.height || obj2.y > +obj1.y + +obj1.height) {
console.log('false');
return false;
}
console.log('false');
return true;
}
I have already tried to get the number value of the object property, as you can see. Didn't work
Also tried parseInt(), which didn't work.
I suppose I can put the values seperately as parameters in the fuctions but I was hoping to keep it as short as possible, because kids need to use it.
You need to add a grouping operator:
... + (parseInt(ob2x) + parseInt(ob2width)) + ...
to isolate that part of the expression so that + is seen as addition. Otherwise, the full expression keeps it as concatenation, even though you convert those to values to numbers (because if a string is anywhere in the expression being evaluated, + means concat).
E.g.
var x = 5;
var y = 6;
console.log('Sum: ' + x + y); // 56
console.log('Sum: ' + (x + y)); // 11

Categories

Resources