Skip to content
Advertisement

Merging non-matching timeseries arrays in JS?

My question is of data manipulation.

Say I have multiple data arrays with the structure as follows:

[
  [timestamp1, value1],
  [timestamp2, value2],
  [timestamp3, value3],
  ...
  [timestampN, valueN]
]

With real data it could look e.g. like this:

[
  [1637837518000, 1.7],
  [1637837519000, 0.1],
  [1637837520000, 1.3],
  ...
  [1637837600000, 2.2]
]

The I need to merge multiple of such arrays into one, which is is easy if the time axes are matching. If I have e.g. three short sample arrays:

const arr1 = [
  [1637837518000, 1.7],
  [1637837519000, 0.1],
  [1637837520000, 1.3]
];
const arr2 = [
  [1637837518000, 4.5],
  [1637837519000, 0.3],
  [1637837520000, 7.2],
];
const arr3 = [
  [1637837518000, 1.2],
  [1637837519000, 2.1],
  [1637837520000, 3.0]
];

they would be merged into the following array, retaining the common time axis:

[
  [1637837518000, 1.7, 4.5, 1.2],
  [1637837519000, 0.1, 0.3, 2.1],
  [1637837520000, 1.3, 7.2, 3.0]
]

This is straightforward, but if the arrays are of different lengths where some arrays have a data point on a timestamp where others do not, what would be most efficient way of performing such parsing? I’m asking for an efficient solution as there can be a lot of data and slow parsing would result in a bad user experience. Also, the timestamps should be in order in the resulting array. It can be expected that within a single array the timestamps are in order.

Sample data for the problem I’m trying to solve:

const arr1 = [
  [1637837518000, 1.7],
  [1637837519000, 0.1],
  [1637837520000, 1.3],
  [1637837521000, 6.4],
  [1637837522000, 2.2],
  [1637837523000, 2.1]
];
const arr2 = [
  [1637837517000, 600.32],
  [1637837520000, 578.98],
  [1637837523000, 612.76]
];
const arr3 = [
  [1637837518000, 45.3],
  [1637837520000, 34.8],
  [1637837522000, 40.0],
  [1637837524000, 41.5]
];

And the desired result would be:

[
  [1637837517000, null, 600.32, null],
  [1637837518000, 1.7,  null,   45.3],
  [1637837519000, 0.1,  null,   null],
  [1637837520000, 1.3,  578.98, 34.8],
  [1637837521000, 6.4,  null,   null],
  [1637837522000, 2.2,  null,   40.0],
  [1637837523000, 2.1,  612.76, null],
  [1637837524000, null, null,   41.5]
]

There is no need for interpolation, so if a timestamp does not exist in any data array, there need not be any entry in the result array of that timestamp.

Advertisement

Answer

The below should solve the problem resonably efficiently:

const arr1 = [
  [1637837518000, 1.7],
  [1637837519000, 0.1],
  [1637837520000, 1.3],
  [1637837521000, 6.4],
  [1637837522000, 2.2],
  [1637837523000, 2.1]
];
const arr2 = [
  [1637837517000, 600.32],
  [1637837520000, 578.98],
  [1637837523000, 612.76]
];
const arr3 = [
  [1637837518000, 45.3],
  [1637837520000, 34.8],
  [1637837522000, 40.0],
  [1637837524000, 41.5]
];

function concat(...arrs){
  const result = {};
  for(var i=0;i<arrs.length;i++){
    for(let [ts,val] of arrs[i]){
      result[ts] = result[ts] || new Array(arrs.length + 1).fill(null);
      result[ts][0] = ts;
      result[ts][i+1] = val;
    }     
  }
  return Object.values(result).sort( (a,b) => a[0] - b[0]);
}

console.log(concat(arr1,arr2,arr3));
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement