3

Hi I have come across a strange JS/JQuery issue.

I have 2 arrays which contain a timestamp and a value. I have merged these 2 arrays together so that if the timestamp is the same in both arrays create one array with the timestamp, value1 and value2. (value1 is in the first array, value2 is in the second array)

Here is the code I have written to do this. value[0] is the timestamp

var combinedArray = [];
$.each(data.new, function(key, value) {
    combinedArray[value[0]] = [value[0], value[1]];
});

$.each(data.repeat, function(key, value) {
    combinedArray[value[0]].push(value[1]);
});

If I log this to the browser it looks like so:

Image

As you can see the combinedArray does have multiple values so I'm not sure why the length is 0.

The reason this is an issue is because I need to loop over the combinedArray which I currently cannot do.

Lukerayner
  • 412
  • 6
  • 23
  • Create a jsfiddle showing your code – Akshay Apr 25 '19 at 09:25
  • You should use an object instead of an array for `combinedArray`, then get length with `Object.keys(combinedArray).length`. – Kévin Bibollet Apr 25 '19 at 09:26
  • 3
    you are just outside of the valid index, which is max a 32 bit positive integer. – Nina Scholz Apr 25 '19 at 09:27
  • 4
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length As an array can only have 2**32 values, any index over that value will be treated as a property, so the length of your array will be 0, as it has no elements, only properties. – Matt Ellen Apr 25 '19 at 09:27
  • @MattEllen but the number of elements in the console.log here obviously less than 2**32, or am I missing something? – holydragon Apr 25 '19 at 09:30
  • @holydragon you are setting the index to the timestamp. for example: `var a = []; a[123091823019823] = 44;` the length of `a` will be 0, because 123091823019823 is greater than 2**32. – Matt Ellen Apr 25 '19 at 09:32
  • @iArcadia I proposed the same, but get -4 in 2 minutes. Maybe you have an idea why? – Volod Apr 25 '19 at 09:33
  • @holydragon if you create an array `a = []` and assign to a particular index `a[33] = 'hi'` then the previous 33 values will be `undefined`. But if the index you assign to is greater than 2**32 then the previous values will not be created. – Matt Ellen Apr 25 '19 at 09:34
  • 3
    Disagree to the dupe. – Jonas Wilms Apr 25 '19 at 09:35
  • @mattEllen that would be a good answer :) – Jonas Wilms Apr 25 '19 at 09:35

2 Answers2

2

The indices of your array are outside of the valid range of a positive 32 bit interger value.

From Array#length:

The length property of an object which is an instance of type Array sets or returns the number of elements in that array. The value is an unsigned, 32-bit integer that is always numerically greater than the highest index in the array.

var array = [];
array[1541030400000] = 'foo';

console.log(array.length);
console.log(array);
console.log(array[1541030400000]);

To overcome this problem, you could take timestamps without milli seconds and take a smaller value as index for the array.

The array is then iterable with standard methods.

Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
2

As stated here the length of an array must be less than 2 to the power of 32.

Your timestamps are larger than 2 to the power of 32, so cannot be array indices.

If you create an array a = [] and assign to a particular index a[33] = 'hi' then the previous 33 values will be undefined. But if the index you assign to is greater than 2**32 then the previous values will not be created, so the length of your array will be 0.

If you use a value over 2**32 as an index it will be treated as a property instead. So, if you want you can try iterating over the properties of the array.

I suggest that instead of combinedArray[value[0]], which will create properties, the following will get you an array you can iterate over:

var combinedArray = [];
var timestampIndices = [];

$.each(data.new, function(key, value) {
    combinedArray.push([value[0], value[1]]);
    timestampIndices.push(value[0]);
});

$.each(data.repeat, function(key, value) {
    let index = timestampIndices.indexOf(value[0]);
    combinedArray[index].push(value[1]);
});
Matt Ellen
  • 11,268
  • 4
  • 68
  • 90