Map where each date holds an array, implementation problem - javascript

I would need a structure where each key (Date) holds an array of integers.
I have tried the following but it does not seem to be working.
I create a record with the array and then set all its values to 0, although it still seems they are NaN:
The first statement creates a record as a Date with an associated array of a length defined by a variable.
Dictionary.set(Meteor.jira.formatDate(moment(date),[arrayLenght]);
//initialize the array with 0 values
var i;
for (i = 0; i < arrayLenght; i++) {
Dictionary.set(Meteor.jira.formatDate(moment(date))[i]=0);
}
}

Fill array first, then put it into dictionary.
You can update it's value changing any variable that contains reference to your array.
let Dictionary = new Map();
let arrayLenght = 6;
let key = "2018-11-15" //Meteor.jira.formatDate(moment(date))
let arr = Array(arrayLenght).fill(0);
Dictionary.set(key, arr);
let value = Dictionary.get(key);
console.log(JSON.stringify(value));
value[2] = 1;
value.unshift(33);
arr.unshift(15);
console.log(JSON.stringify(Dictionary.get(key)))

Related

How to push new elements to an array with undefined index in JavaScript

I want to create array once and then just push values to it with any index , but i get Cannot read property 'push' of undefined error
I have following scenario
var neg = [];
I want to use push randomly with any index
neg[0].push([1,2]);
or
neg[22].push([1,2]);
right now I want to define manually like neg[0] = []; , Is there any one way where i can just push to any index i want ?
Here's a quick way to do exactly what you want.
var arr = [];
(arr[0]=[]).push([1,2]);
console.log(arr)
Also it's safer to check if an array already exists at this index, otherwise it will be replaced with an empty array – the above code will replace the array with an empty one if it already exists.
// creates an array at index 0 only if there's no array at this index.
// pushes an array of [1, 2] to the existing array at 0 index
// or the newly created empty one.
(arr[0] || (arr[0] = [])).push([1, 2]);;
var arr = [];
arr[0] = [1];
(arr[0]||(arr[0]=[])).push(2,3);
console.log(arr)
Push will add elements to the end of an array. For example:
var neg = [];
neg.push(3); //this will add the number 3 to the end of your array
The problem here is your trying to add a value to an undefined element:
var neg = [];
neg[0].push([1,2]); // <-- neg[0] is not defined at this moment, and you're treating it as an array object.
If you define your elements as an array, you will not get such an error:
var neg = [];
neg[0] = [];
neg[22] = [];
neg[0].push([1,2]);
neg[22].push([1,2]);
Alternatively (and this is probably what you're probably looking for), you can set the value for any element of your array with the desired index:
var neg = [];
neg[0] = [1,2];
neg[22] = [1,2];
You are going to have to set it to an empty array before you can push it.
neg[0] = neg[0] || []
neg[0].push([1,2]);
You can specify how large the array will be if you know ahead of time, for example var neg = new Array(40); will create a new array with 40 undefined elements.
Once that is created, you can change the value at any index as long as 0 <= index <= 39.
You can use array.splice(your_index, 0, your_element); to push an element into an array at the given index.

Nodejs code is not executing as expected

I am trying the below line of codes. I want to save the numbers after each iteration of outer while loop in an array named sn. But, after each iteration sn contains only the numbers of last iteration. May be I am missing whole concept of sync and async.
function test() {
var numbers = [0, 2, 7, 0];
var check = true;
var sn = [];
var p = 0;
while (check) {
var index = numbers.indexOf(Math.max(...numbers));
var value = Math.max(...numbers);
numbers[index] = 0;
for (var i = value; i > 0; i--) {
var temp = ++index;
index = temp % (numbers.length);
numbers[index] += 1;
}
console.log("numbers", numbers);
if (sn.includes(numbers)) { check = false };
sn.push(numbers);
console.log("hey there=========");
}
}
test();
There is nothing to do with sync or async here.
Here what is happening is that, you are trying to push 'numbers' array to 'sn' array.
Statement is "sn.push(numbers);"
So here we are pushing the Object reference of numbers array to 'sn', means you are not making a copy of numbers array and pushing to 'sn'.
You are just pushing the Memory reference of 'numbers' array.
So during first iteration, 'sn' will have exact value as you calculates.
But during the second iteration 'sn' will have two arrays. But those two values are same and points to the same memory location of 'number'.
So here what you should do is create a clone of 'numbers' array during each iteration.
if (sn.includes(numbers)) { check = false };
var cloneArray = numbers.slice(0);
sn.push(cloneArray);
This if statement: if (sn.includes(numbers)) { check = false }; will never be true because the Array.prototype.includes() method does not accept an array as a parameter; only individual elements. numbers is an array and thus will never be truthy.
If you are trying to see if an array contains a sub-array. The answer that Mild Fuzz has in this stack overflow: Javascript array contains/includes sub array should work.

What is wrong with javascript?

I wrote some simple javascript code, but it does not return the expected result.
var arr = new Array();
var firstobj = {
cta: 0,
ccc: 0,
crc: 0
}
for (var ta = 1; ta <= 10; ta++) {
arr[ta] = firstobj;
}
arr[6].cta = 1;
console.log(arr);
I only change cta value of 6th element, but it changes for all elements.
Expected:
[{cta:0, ccc:0, crc:0}, ..., {cta:1, ccc:0, crc:0}, {cta:0, ccc:0, crc:0}, ...]
// ^ 6th element
Actual:
[{cta:1, ccc:0, crc:0, ...] // All have 1
Objects in Javascript are assigned by pointer (well technically JS doesn't have pointers, but it works like a pointer does in other languages). So, you have filled your array so that every element contains a pointer-like reference to the exact same object. Thus, when you change that object, you see the change everywhere because there's only one object and you changed it.
If you want to initialize an array with separate objects, you have to create a new object or clone an existing object and assign that separate object into each element of your array.
For example, you could do that like this:
var myArray = [];
var obj;
// Also, arrays start from 0, not from 1.
for (var i = 0; i < 10; i++) {
// create a new object for each item in the array
obj = {cta:0, ccc:0, crc:0};
myArray[i] = obj;
}
myArray[6].cta = 1;
document.write(JSON.stringify(myArray));
you assigned the same object reference to all values in the array
make it (use Object.create)
for (var ta = 1; ta <= 10; ta++)
{
arr [ta] = Object.create( firstobj );
}
When you save the same firstobj to your array it saved by reference so when you changing one of the values it changes all of them, my suggestion is to create a new object for each element in your array.
var arr = new Array();
for (var ta = 1; ta <= 10; ta++) {
arr [ta] = { cta:0,
ccc:0,
crc:0
};
}
arr[6].cta=1;
console.log(arr);
Only the 6th element's cta value must be 1, but all elements cta
values change.
all the elements in your array(apart from element at zero index , which would be undefined in your case) are referring to the same object so if you change property in one element it is refelected across all elements
Each element in array is referring to same object.
So when you change object value it is reflected in all elements.

how to generate arrays automatically in javascript?

I want to make a loop that makes arrays automatically and assign the values to it.
The problem is how to generate the array itself automatically.
for(var attGetter=1; attGetter <= num; attGetter++){
var catesArray1 = new Array();
for(var atttGetterArray=1; atttGetterArray <= series; attGetterArray++){
idOfInput = "cate"+chartGetter+"_series"+attGetterArray;
catesArray1.push($("#"+idOfInput).val());
}
}
I want the loop to generate the array itself automatically like
catesArray1
catesArray2
catesArray3
and so on..
You need an object or an array to hold the multiple arrays you wish to create. Maybe something you are looking for is like the following?
var arrayHolder = new Array();
for(var attGetter=1; attGetter <= num; attGetter++){
var catesArray = new Array();
for(var attGetterArray=1; atttGetterArray <= series; attGetterArray++){
idOfInput = "cate"+chartGetter+"_series"+attGetterArray;
catesArray.push($("#"+idOfInput).val());
}
arrayHolder.push(catesArray);
}
If you want the arrays to be in global namespace, You can try
window['catesArray' + attGetter] = [];
...
window['catesArray' + attGetter].push(...)
Else you can create a hash object and use it to hold the reference
var obj = {};
.....
obj['catesArray' + attGetter] = [];
.....
obj['catesArray' + attGetter].push(...)
In that case you will have to create one new array that holds all the cacatesArrays from first for loop
var catesArrayContainer = new Array(); //<<<---------------------
for(var attGetter=1; attGetter <= num; attGetter++){
var catesArray = new Array();
for(var atttGetterArray=1; atttGetterArray <= series; attGetterArray++){
idOfInput = "cate"+chartGetter+"_series"+attGetterArray;
catesArray.push($("#"+idOfInput).val());
}
catesArrayContainer.push(catesArray); //<<<--------------------
}
EDIT :
This happens because the scope of variable catesArray1 was limited. When the loop enters next iteration the catesArray1 gets reinitialized, thus losing all the previously stored values...
Now in the code I have posted, we are storing every instance of catesArray1 in another array, and your values persist out side of the for loop
You can do something like this for 4 arrays of 5 elements each
yourarray=[];
for (i = 0; i <4; i++) {
temparray=[];
for (j = 0; j < 5; j++) {
temparray.push($('#'+whateverID+'_'+i+'_'+j)) //your values here
}
yourarray.push(temparray);
}
Check it on this JSFiddle. open chrome console to see array
If you want to create array within loop from index
You can use eval to evaluate javascript from strings but i wont use that unless there is no other way. you can see both above and eval method in this Fiddle. Open Chrome console to see array values
Just a comparison of using eval and 2D array
Open console in chrome while you run this jsFiddle and you will see the difference in eval and 2darray in context of this question.
You should assign them to an object. In this case, make an object variable before the first for-loop to hold all arrays:
var allArrays = {};
for(var attGetter=1; attGetter <= num; attGetter++){
var currentArray = allArrays['catesArray' + attGetter] = new Array();
for(var atttGetterArray=1; atttGetterArray <= series; attGetterArray++){
idOfInput = "cate"+chartGetter+"_series"+attGetterArray;
currentArray.push($("#"+idOfInput).val());
}
}
Instead of attempting to create & allocate dynamically named variables, I would think of this more of an array of array's if you will. In other words, create an array that holds all of the arrays you want:
var collections = []; // Literal notation for creating an array in JS
From here, it's a matter of making each value you create within this array its own array:
var n = 10; // Total amount of arrays you want
for (var i = 0; i < n; i++) {
var values = [];
// Have another loop that fills in the values array as expected
collections.push(values); // Each element at collections[i] is its own array.
}
If you truly need named elements, you could potentially do something very similar with just an object {} instead, and refer to each element by a name you create.
var collections = {}; // Literal notation for an object in JS
var n = 10; // Total amount of arrays you want
for (var i = 0; i < n; i++) {
var values = []; // Literal notation for an array in JS
// Fill in the values array as desired
var name = 'arr' + i; // How you'll refer to it in the object
collections[name] = values;
}
I suggest the former though, since it does not sound like you need to have explicit names on your arrays, but just want multiple layers of arrays.

Can't reference array by index

I have an array defined as:
var subjectCache = [];
I then have some code to build it up, which is working ok.
However, if I try to reference the array by an index, e.g.:
var x = subjectCache[0];
or
var x = subjectCache[1];
I get undefined.
Also subjectCache.length is always 0 (zero).
if I try to reference it by its key, e.g.:
var x = subjectCache['12345'];
it works.
Is this normal? Shouldn't I be able to reference it by its index whatever?
I'm using Internet Explorer, if it makes a difference (and it probably does :( )
[Edit]
this is the code I'm using to build the array, although I really don't think it is to blame.
It's a callback from a webservice call. This is working fine and the array is being populated.
var subjectCache = [];
var subjectCacheCount = 0;
function refreshSubjectsCallback(data) {
// update subjects
// loop through retrieved subjects and add to cache
for( i=0; i < data.length; i++ )
{
var subject = data[i];
var subjectid = subject.SubjectId;
subjectCache[subjectid] = subject;
subjectCacheCount += 1;
}
}
[/Edit]
You're probably assigning keys manually instead of using subjectCache.push() to add new elements to the array:
var array = [];
array['foo'] = 'bar';
console.log(array.length); // 0
The length attribute isn't going to reflect those changes the way you'd expect:
> var a = [];
undefined
> a[100] = 2; // The previous `100` entries evaluate to `undefined`
2
> a.length;
101
Instead, use an object:
var object = {};
object['foo'] = 'bar';
for (var key in object) {
var value = object[key];
console.log(value);
}
From your symptoms, it sounds like you are trying to treat the array as an associative array.
In Javascript, arrays work like this:
var a = [];
a[1] = 10;
alert(a.length);
Objects work like this:
var o = {};
o.myProp = true;
o["myOtherProp"] = false;
Arrays only work with numeric keys not strings. Strings assign properties to the object, and aren't counted as part of length nor it's numeric indices.
When building the array, make sure you are assigning to a numeric position within the array.
No, it will not work, because you haven't created arrays but objects.
you will have to access it by its key.
var x = subjectCache['12345'];
If this works and subjectCache.length doesn't, I think you are making an object not an array. You are confused.
Somewhere along the road you lost the array, and the variable subjectCache points to a different kind of object.
If it was an array, it can't have the length zero and contain an item that is reachable using subjectCache['12345']. When you access an item in an array it doesn't make any difference if you use a numeric index or a string representing a number.

Categories

Resources