Reputation: 339
I'm trying to fill an array with missing intermediate data
My data input is like this
var data = [[5.23,7],[5.28,7],[5.32,8],[5.35,8]];
I wanna fill the array with missing value but I need to respect this rule:
So the results in this case would be
var data = [[5.23,7],[5.24,7],[5.25,7],[5.26,7],[5.27,7],[5.28,7],[5.29,8],[5.30,8],[5.31,8],[5.32,8],[5.33,8],[5.34,8],[5.35,8]];
This little piece of code works, but I don't know how to put in loop and how to write a while loop that pass every time the new length of the array
var data = [[5.23,7],[5.28,7],[5.32,8],[5.35,8]];
if (data[1][0]-data[0][0] > 0.01) {
data.push([data[0][0]+0.01,data[1][1]]);
data.sort(function (a, b) { return a[0] - b[0]; });
} else {
check the next element
}
console.log(data);
Any idea?
Upvotes: 0
Views: 593
Reputation: 3562
Here's another idea... I thought it might feel more natural to loop through the sequence numbers directly.
Your final array will range (in this example) from 5.23 to 5.35 incrementing by 0.01. This approach uses a for loop starting going from 5.23 to 5.35 incrementing by 0.01.
key points
+
operator).100*(5.31-5.23)
equals 8
(so 5.31
belongs in output[8]
).5.31
), just find the first element in the data array with a higher 1st value and use its 2nd value - this is a corollary of your requirement. Because 5.31 <= 5.28
is false, don't use 7
(from [5.28,7]
). Because 5.31 <= 5.32
is true, use 8
(from [5.32,8]
).EDIT
I improved the performance a bit - (1) initialize output instead of modifying array size, (2) work in multiples of 100 instead of continuously rounding from floating point to hundredths.
I ran 5000 iterations on a longer example and, on average, these modifications make this approach 3x faster than Redu's (where the original was 2x slower).
var data = [[5.23,7],[5.28,7],[5.32,8],[5.35,8]];
var output = Array((data[data.length-1][0]-data[0][0]).toFixed(2)*100+1)
function getIndex(value){
return (value-data[0][0]*100)
}
for( var i = 100*data[0][0]; i <= 100*data[data.length-1][0]; i++ ){
output[getIndex(i)] = [i/100, data.find( d => i <= 100*d[0] )[1]]
}
//console.log(output)
// Performance comparison
function option1(data){
let t = performance.now()
var output = Array((data[data.length-1][0]-data[0][0]).toFixed(2)*100+1)
function getIndex(value){
return (value-data[0][0]*100)
}
for( var i = 100*data[0][0]; i <= 100*data[data.length-1][0]; i++ ){
output[getIndex(i)] = [i/100, data.find( d => i <= 100*d[0] )[1]]
}
return performance.now()-t
}
function option2(data){
let t = performance.now()
newData = data.reduce((p,c,i,a) => i ? p.concat(Array(Math.round(c[0]*100 - a[i-1][0]*100)).fill()
.map((_,j) => [Number((a[i-1][0]+(j+1)/100).toFixed(2)),c[1]]))
: [c],[]);
return performance.now()-t
}
var testdata = [[1.13,4],[2.05,6],[5.23,7],[5.28,7],[5.32,8],[5.35,8],[8.91,9],[10.31,9]];
var nTrials = 10000;
for(var trial=0, t1=0; trial<=nTrials; trial++) t1 += option1(testdata)
for(var trial=0, t2=0; trial<=nTrials; trial++) t2 += option2(testdata)
console.log(t1/nTrials) // ~0.4 ms
console.log(t2/nTrials) // ~0.55 ms
Upvotes: 1
Reputation: 26161
Array.prototype.reduce()
is sometimes handy to extend the array. May be you can do as follows;
var data = [[5.23,7],[5.28,7],[5.32,8],[5.35,8]],
newData = data.reduce((p,c,i,a) => i ? p.concat(Array(Math.round(c[0]*100 - a[i-1][0]*100)).fill()
.map((_,j) => [Number((a[i-1][0]+(j+1)/100).toFixed(2)),c[1]]))
: [c],[]);
console.log(newData);
var data = [[1.01,3],[1.04,4],[1.09,5],[1.10,6],[1.15,7]],
newData = data.reduce((p,c,i,a) => i ? p.concat(Array(Math.round(c[0]*100 - a[i-1][0]*100)).fill()
.map((_,j) => [Number((a[i-1][0]+(j+1)/100).toFixed(2)),c[1]]))
: [c],[]);
console.log(newData);
Upvotes: 1
Reputation: 4612
I propose this solution :
var data = [[5.23,7],[5.28,7],[5.32,8],[5.35,8]];
var res = [];
data.forEach((item, index, arr) => {
res.push(item);
var temp = item[0];
while (arr[index+1] && arr[index+1][0]-temp > 0.01){
temp += 0.01;
res.push([temp, arr[index+1][1]]);
}
});
console.log(res);
Upvotes: 0