Javascript 用中间值填充数组
Javascript fill array with intermediate value
我正在尝试用缺少的中间数据填充数组
我的数据输入是这样的
var data = [[5.23,7],[5.28,7],[5.32,8],[5.35,8]];
我想用缺失值填充数组,但我需要遵守这条规则:
- 二维数组的第一个值必须是下一个序列号,所以 5.23
... 5.24 ... 5.25 ...
- 二维数组的第二个值必须与第 i+1 个元素相同
值
所以这种情况下的结果是
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]];
这段代码有效,但我不知道
如何放入循环
以及如何编写一个 while 循环,每次数组的新长度
var 数据 = [[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(数据);
有什么想法吗?
Array.prototype.reduce()
有时可以方便地扩展数组。也许你可以这样做;
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);
我提出这个解决方案:
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);
这是另一个想法...我认为直接遍历序列号可能感觉更自然。
您的最终数组 运行ge(在本例中)从 5.23 到 5.35,递增 0.01。这种方法使用 for 循环,从 5.23 开始到 5.35,递增 0.01。
重点
- 舍入:在 x100 中工作,然后向下划分以避免浮点舍入问题。
我使用 toFixed(2) 舍入到接近百分之一,然后转换回数字(使用前导 +
运算符)。
- 索引:识别5.23是零索引,每个索引递增1/100,您可以从数值计算索引,例如。
100*(5.31-5.23)
等于 8
(所以 5.31
属于 output[8]
)。
- 第二个值:给定一个数值(例如
5.31
),只需在数据数组中找到第一个值较高的第一个元素并使用其第二个价值 - 这是您要求的必然结果。因为 5.31 <= 5.28
是假的,所以不要使用 7
(来自 [5.28,7]
)。因为 5.31 <= 5.32
为真,所以使用 8
(来自 [5.32,8]
)。
编辑
我稍微改进了性能 - (1) 初始化输出而不是修改数组大小,(2) 以 100 的倍数工作,而不是从浮点连续舍入到百分之一。
I 运行 在一个较长的示例上进行 5000 次迭代,平均而言,这些修改使此方法比 Redu 的方法快 3x(原始方法慢 2 倍)。
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
我正在尝试用缺少的中间数据填充数组
我的数据输入是这样的
var data = [[5.23,7],[5.28,7],[5.32,8],[5.35,8]];
我想用缺失值填充数组,但我需要遵守这条规则:
- 二维数组的第一个值必须是下一个序列号,所以 5.23 ... 5.24 ... 5.25 ...
- 二维数组的第二个值必须与第 i+1 个元素相同 值
所以这种情况下的结果是
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]];
这段代码有效,但我不知道 如何放入循环 以及如何编写一个 while 循环,每次数组的新长度
var 数据 = [[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(数据);
有什么想法吗?
Array.prototype.reduce()
有时可以方便地扩展数组。也许你可以这样做;
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);
我提出这个解决方案:
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);
这是另一个想法...我认为直接遍历序列号可能感觉更自然。
您的最终数组 运行ge(在本例中)从 5.23 到 5.35,递增 0.01。这种方法使用 for 循环,从 5.23 开始到 5.35,递增 0.01。
重点
- 舍入:在 x100 中工作,然后向下划分以避免浮点舍入问题。
我使用 toFixed(2) 舍入到接近百分之一,然后转换回数字(使用前导+
运算符)。 - 索引:识别5.23是零索引,每个索引递增1/100,您可以从数值计算索引,例如。
100*(5.31-5.23)
等于8
(所以5.31
属于output[8]
)。 - 第二个值:给定一个数值(例如
5.31
),只需在数据数组中找到第一个值较高的第一个元素并使用其第二个价值 - 这是您要求的必然结果。因为5.31 <= 5.28
是假的,所以不要使用7
(来自[5.28,7]
)。因为5.31 <= 5.32
为真,所以使用8
(来自[5.32,8]
)。
编辑
我稍微改进了性能 - (1) 初始化输出而不是修改数组大小,(2) 以 100 的倍数工作,而不是从浮点连续舍入到百分之一。
I 运行 在一个较长的示例上进行 5000 次迭代,平均而言,这些修改使此方法比 Redu 的方法快 3x(原始方法慢 2 倍)。
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