Reassign variables in if/else (Javascript) - javascript

How can I achieve a reassigned list (or any other value for that matter) in javascript?
I've tried to do as I'd do in python, and make a empty list and assign it if my conditions are met, but it seems that javascript will fall right back on what's assigned out of my if/else
My goal is to achieve something like this:
let data1 = [];
let data2 = [];
let data3 = [];
document.addEventListener("DOMContentLoaded", function(){
if (document.getElementById('minus').checked) {
let data1 = [-64, 31, 23, 34, 23, 30, 50, 43, 29, 64, 22, 34];
let data2 = [-23, 45, 83, 74, 99, 83, 64, 72, 50, 44, 36, 45];
let data3 = [-64, 75, 43, 24, 63, 72, 88, 24, 84, 93, 45, 60];
} else {
let data1 = [64, 31, 23, 34, 23, 30, 50, 43, 29, 64, 22, 34];
let data2 = [23, 45, 83, 74, 99, 83, 64, 72, 50, 44, 36, 45];
let data3 = [64, 75, 43, 24, 63, 72, 88, 24, 84, 93, 45, 60];
}
});
//Further code that uses the variables we just set
fiddle on my issue:
https://jsfiddle.net/vk8swjc3/

You're currently redefining all of those data variables by saying let again. Remove the lets and do data1 = [-64, 31, 23, 34, 23, 30, 50, 43, 29, 64, 22, 34] directly to reassign them.

Two problems:
If you use let x inside a block, you're creating a new variable x in the inner scope. Remove let and you're reassigning the original x.
If you reassign them inside a DOMContentLoaded callback, the new values won't be available to the immediately running code after you set up that callback (only in the callback itself, or once the callback has run). See https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
Here's a demo of the order of execution:
console.log('top')
document.addEventListener("DOMContentLoaded", () => {
console.log('DOMContentLoaded')
executeWithinCallback()
})
const executeWithinCallback = () => {
console.log('after DOMContentLoaded')
}
console.log('bottom')

When you are use var, let or const on a scope(curly braces) you are defined a variable that you can use only inside of that scope.
So if you want to use top level variable in another scope then you shouldn't use var, let or const to assign a value to variable.
You can look here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

Having addressed the variable scoping issues that you had in your initial post we can now look at the larger part of your question which seems to be the matter of changing data, or at least setting initial data based on the state of a control.
Your fiddle is working as intended, but not as you expect it to. If you console.log() any of the data arrays after the conditional within the DOMContentLoaded you will see the updated array.
let data1 = [];
let data2 = [];
let data3 = [];
document.addEventListener("DOMContentLoaded", function(){
if (document.getElementById('minus').checked) {
data1 = [-64, 31, 23, 34, 23, 30, 50, 43, 29, 64, 22, 34];
data2 = [-23, 45, 83, 74, 99, 83, 64, 72, 50, 44, 36, 45];
data3 = [-64, 75, 43, 24, 63, 72, 88, 24, 84, 93, 45, 60];
} else {
data1 = [64, 31, 23, 34, 23, 30, 50, 43, 29, 64, 22, 34];
data2 = [23, 45, 83, 74, 99, 83, 64, 72, 50, 44, 36, 45];
data3 = [64, 75, 43, 24, 63, 72, 88, 24, 84, 93, 45, 60];
}
console.log(data1);
});
// [64, 31, 23, 34, 23, 30, 50, 43, 29, 64, 22, 34]
However, by the time that runs you have already set up your chart with the empty array values and it has rendered. Changing the values of the data arrays after that will have no effect on the rendered chart, nor on the values of the arrays assigned to chartData.datasets[n].data
In order to update the chart you need to change these dataset values and call update on the the chart.
let barVertical = document.getElementById("barVertical");
let barVerticalChart = new Chart(barVertical, {
type: "bar",
data: chartData,
options: chartOptions,
});
const minus = document.getElementById('minus');
minus.addEventListener('change', (e) => {
if (e.target.checked) {
chartData.datasets[0].data = [-64, 31, 23, 34, 23, 30, 50, 43, 29, 64, 22, 34];
chartData.datasets[1].data = [-23, 45, 83, 74, 99, 83, 64, 72, 50, 44, 36, 45];
chartData.datasets[2].data = [-64, 75, 43, 24, 63, 72, 88, 24, 84, 93, 45, 60];
} else {
chartData.datasets[0].data = [64, 31, 23, 34, 23, 30, 50, 43, 29, 64, 22, 34];
chartData.datasets[1].data = [23, 45, 83, 74, 99, 83, 64, 72, 50, 44, 36, 45];
chartData.datasets[2].data = [64, 75, 43, 24, 63, 72, 88, 24, 84, 93, 45, 60];
}
barVerticalChart.update();
});
Updated fiddle: https://jsfiddle.net/q3tmon21/
Or, to simply make your code run as you seem to expect, using the conditionally set arrays on the first render, simply move all the code that comes after it into the DOMContentLoaded listener.
let data1 = [];
let data2 = [];
let data3 = [];
document.addEventListener("DOMContentLoaded", function(){
if (document.getElementById('minus').checked) {
data1 = [-64, 31, 23, 34, 23, 30, 50, 43, 29, 64, 22, 34];
data2 = [-23, 45, 83, 74, 99, 83, 64, 72, 50, 44, 36, 45];
data3 = [-64, 75, 43, 24, 63, 72, 88, 24, 84, 93, 45, 60];
} else {
data1 = [64, 31, 23, 34, 23, 30, 50, 43, 29, 64, 22, 34];
data2 = [23, 45, 83, 74, 99, 83, 64, 72, 50, 44, 36, 45];
data3 = [64, 75, 43, 24, 63, 72, 88, 24, 84, 93, 45, 60];
}
let labels = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
let chartData = {
labels: labels,
datasets: [
{
label: "Data1",
data: data1,
backgroundColor: "rgba(154, 18, 179, .7)",
},
{
label: "Data2",
data: data2,
backgroundColor: "rgba(232, 126, 4, .7)",
},
{
label: "Data3",
data: data3,
backgroundColor: "rgba(0, 230, 64, .7)",
},
],
};
let barVertical = document.getElementById("barVertical");
let barVerticalChart = new Chart(barVertical, {
type: "bar",
data: chartData,
options: chartOptions,
});
});

Related

How can I split the result of an array in an ejs into multiple pages?

I'm building a blog using nodejs, express and mongodb. When I go to create an article, it is saved in a database that includes all the articles. On the homepage I used an array with object to store all the articles locally and get the title, content and more from them.
I wanted to know how you can set up page navigation so that previews of only 10 articles are shown per page (first page 10 articles; second page 10 articles and so on). So I wanted to know how to set a radius of objects to take from the array (first page 1 to 10; second page 11 to 20 and so on).
Let say you have an array with 100 element and you want to split to get an array of 10 x 10 element (10 pages of 10 element)
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100];
let pages = [];
while(arr.length > 0) {
pages.push(
arr.splice(0, 10)
);
}
console.log(arr)
console.log(pages)
Now you have an array with 10 sub-array of 10 elements each.
Image you want to print the page number 5 you have yo do something like this :
let page = 5;
let articles = pages[page-1]
for(let article of articles ) {
// render your article preview here
}
This is just an exemple to give you an idea about how to split an array into multiple pages ;)

Do you know why executing the following expressions take more time than the same within a function call in javascript?

I'm trying to compare the difference in terms of execution time in JS between running some expressions sequentially versus running the same expressions within a function call.
Given the following code:
const t1 = Date.now();
console.log(Array.from(Array(500)).map((i, idx) => idx));
const t2 = Date.now();
console.log('t=', t2 - t1, 'ms', t2, t1);
function traverseArrAndPrint() {
console.log(Array.from(Array(500)).map((i, idx) => idx));
}
const t3 = Date.now();
traverseArrAndPrint();
const t4 = Date.now();
console.log('t=', t4 - t3, 'ms', t4, t3);
Now look at the output:
node a.js
[
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99,
... 400 more items
]
t= 8 ms 1620926365937 1620926365929
[
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99,
... 400 more items
]
t= 1 ms 1620926365938 1620926365937
Why would a function call take less time to execute than the sequential expressions before it?

Javascript declare multiple variables with the same values

Maybe I should use some kind of loop or something. But I don't have any idea how to declare this, excluding do it manually.
Is there any solution that will have only a few lines for all of this. Because, there should be 100 variable, despite I only presented 5, I didn't want to type all night.
a1=1; a2=1; a3=1; a4=1; a5=1;
function myfn1() {
a1++;
//unique function code
}
function myfn2() {
a2++;
//unique function code
}
function myfn3() {
a3++;
//unique function code
}
function myfn4() {
a4++;
//unique function code
}
function myfn5() {
a5++;
//unique function code
}
Although this isn't answering your question, I think this approach will help you more in the long run (and probably in the short run too). Check out using an array, which is just a collection of data. Check out the following code.
var arr = [];
for(var i =0; i <= 100; i++){
arr[i] = i;
}
this gives you a collection like this [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100] that you can then manipulate, etc etc.
*edit or if you want them all to have the same value, then
var arr = [];
for(var i =0; i <= 100; i++){
arr[i] = 1;
}

Highcharts series data array

From an ajax call I get the following data back:
18,635,21,177,20,165,22,163,24,162,25,145,19,143,23,139,26,112,27,110,28,104,30,91,29,88,31,68,32,57,36,55,34,53,33,51,35,46,37,44,39,42,43,39,42,39,41,38,38,37,44,36,45,34,48,31,40,31,47,27,49,23,46,21,50,21,52,17,55,17,53,16,51,15,54,12,58,6,57,6,59,4,63,4,56,3,62,2,64,2,100,2,68,1,78,1,60,1,97,1,70,1,65,1,69,1,71,1
Of which every even number should be the key and every odd the value. But I have no idea how to parse it as highcharts data. Somehow I end up with the key being "slice" if I use JSON.parse and the only way I can get it to work normally is by placing it directly into the series data like this (after seperating the odd and even into seperate arrays):
[names[0] + ' years old', parseFloat(values[0])]
Which is great. But then I need to loop through the arrays somehow, pushing everything into the series data and I don't know how to do that. If I make a for loop with this data, how do I insert into the highcharts series data?
If you have that series data in an array, you can process it as follows:
var myData = [18, 635, 21, 177, 20, 165, 22, 163, 24, 162, 25, 145, 19, 143,
23, 139, 26, 112, 27, 110, 28, 104, 30, 91, 29, 88, 31, 68, 32,
57, 36, 55, 34, 53, 33, 51, 35, 46, 37, 44, 39, 42, 43, 39, 42,
39, 41, 38, 38, 37, 44, 36, 45, 34, 48, 31, 40, 31, 47, 27, 49,
23, 46, 21, 50, 21, 52, 17, 55, 17, 53, 16, 51, 15, 54, 12, 58, 6,
57, 6, 59, 4, 63, 4, 56, 3, 62, 2, 64, 2, 100, 2, 68, 1, 78, 1, 60,
1, 97, 1, 70, 1, 65, 1, 69, 1, 71, 1];
var mySeries = [];
for (var i = 0; i < myData.length; i++) {
mySeries.push([myData[i], myData[i + 1]]);
i++
}
Once you have your series data in 'mySeries', you can just set your chart data using:
series:[{
data: mySeries
}]
Alternatively, if you want to add the data after rendering the chart, you can add the series data dynamically using:
chart.series[0].setData(mySeries);
http://jsfiddle.net/Cm3Ps/ (press the 'Add My Data' button).
Actually, the function requires parameter as array of int.
Assume you get a function
drawChartFunction(data) {
// some code here
series: [{ data: data}]
}
You can try it:
array = {9,8,7,6}
var series = [];
for (var i = 0; i < array.length; i++) {
series.push([i, array.[i]]);
}
After the for executed, your series likes
0,9
1,8
2,7
3,6
Then, you call drawChartFunction(series)
So your chart is drawn by using 4 points 0 1 2 3 with their values 9 8 7 6

How to do statistical classification on an array in javascript?

I've got a bunch of numbers in an array and I need to do some statistics on them. I need to know how many of each number there are in the array.
Here's the array:
myArray =
[2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 14, 14, 14, 14, 14, 14, 15, 15, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 27, 27, 28, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 34, 34, 35, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 40, 40, 40, 41, 41, 42, 42, 42, 42, 42, 42, 43, 43, 43, 44, 44, 44, 44, 44, 45, 45, 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 53, 53, 53, 53, 53, 53, 53, 54, 54, 54, 55, 55, 55, 55, 55, 56, 57, 57, 57, 57, 57, 57, 57, 58, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 61, 61, 62, 62, 63, 63, 63, 64, 64, 64, 64, 64, 65, 65, 66, 66, 66, 67, 67, 67, 68, 68, 68, 69, 69, 69, 69, 69, 69, 70, 70, 71, 71, 71, 71, 71, 71, 71, 72, 73, 73, 73, 73, 74, 74, 74, 75, 75, 75, 76, 77, 78, 78, 79, 79, 80, 80, 81, 81, 81, 81, 81, 82, 82, 82, 82, 83, 83, 83, 83, 84, 84, 84, 85, 85, 85, 85, 85, 86, 86, 86, 86, 86, 86, 87, 87, 87, 88, 88, 89, 89, 90, 90, 91, 91, 91, 92, 93, 94, 95, 95, 95, 95, 95, 96, 96, 96, 96, 97, 97, 99, 99, 99, 99, 99, 101, 101, 102, 102, 103, 103, 105, 105, 105, 106, 107, 107, 108, 108, 109, 109, 109, 109, 110, 112, 112, 113, 113, 113, 114, 114, 115, 116, 116, 117, 118, 120, 121, 121, 121, 122, 122, 123, 123, 123, 124, 124, 124, 124, 125, 126, 127, 128, 129, 130, 130, 131, 131, 131, 131, 132, 133, 133, 134, 134, 134, 136, 136, 136, 136, 137, 137, 137, 138, 138, 138, 139, 139, 139, 140, 141, 141, 142, 142, 143, 144, 144, 144, 144, 145, 150, 150, 153, 155, 159, 160, 160, 161, 162, 164, 164, 166, 176, 180, 180, 180, 181, 181, 187, 191, 192, 193, 194, 197, 200, 203, 211, 216, 224, 251, 280, 333]
Here's what I'm using to parse through it currently (which is not working very well):
for (var key in myArray){
var obj = myArray[key];
var count = 0;
while(obj < 30){
myArrayStats[0] = count;
obj++;
}
while(obj > 30 && obj < 40){
myArrayStats[1] = count;
obj++;
}
//etc....
}
Creating a new array using object literals would be much nicer and easier to use, but I'm not sure how to do it.
This just works whether your array is sorted or not, but it shouldn't be much slower than any algorithm that takes advantage of the fact that it is sorted anyways:
var myArrayStats = [];
for(var i = myArray.length; i--;)
myArrayStats[myArray[i]] = (myArrayStats[myArray[i]] || 0) + 1;
console.log(myArrayStats[6]); // Outputs 7
console.log(myArrayStats[10]); // Outputs 5
console.log(myArrayStats[20]); // Outputs 5
If you want to do this for only a portion of the original array than use slice() to get the portion of the array you want and then do the same thing as above on that array:
var mySubArray = myArray.slice(0,30);
var myArrayStats = [];
for(var i = mySubArray.length; i--;)
myArrayStats[mySubArray[i]] = (myArrayStats[mySubArray[i]] || 0) + 1;
console.log(myArrayStats[6]); // Outputs 7
console.log(myArrayStats[9]); // Outputs 7
console.log(myArrayStats[10]); // Outputs undefined
It sounds like you have equally spaced bins and want to count how many values fall in each. Since this question was tagged with jQuery, let's use a utility function from that to avoid an explicit loop to show another way to do things. (I guess PaulPRO's approach is superior though.)
function hist(values, min, max, numBins) {
var bins = [];
var range = max - min;
jQuery.each(values, function(i, value) {
var bin = Math.floor(numBins * (value - min) / range);
bin = Math.min(Math.max(bin, -1), numBins) + 1;
bins[bin] = (bins[bin] || 0) + 1;
});
return bins;
}
We can exercise the above code with the following:
function consoleHist(values, min, max, numBins) {
var bins = hist(values, min, max, numBins);
var step = (max - min) / numBins;
jQuery.each(bins, function(i, count) {
var lower = (i - 1) * step + min;
var upper = lower + step;
if (lower < min) {
lower = -Infinity;
}
if (upper > max) {
upper = Infinity;
}
console.log('[' + lower + ', ' + upper + '): ' + (count || 0));
});
}
consoleHist([-10, 0, 11, 29, 30, 59, 60, 1000], 0, 60, 2);
Produces the following output on the console:
[-Infinity, 0): 1
[0, 30): 3
[30, 60): 2
[60, Infinity): 2
myArray = [2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8,
8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11,
11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 14, 14]
for (var a = myArray, b = {}, i = 0; i < myArray.length; i++) b[a[i]] ? b[a[i]]++ : b[a[i]] = 1;
console.log(JSON.stringify(Object.keys(b)
.map(function(c) {
return [c, b[c]]
})));

Categories

Resources