说我有以下内容:
var sales = [5, 4, 2];
var months = ["Jan 2011", "Apr 2011", "Feb 2012"];
如果我有一个给定的范围说:
var range = ["Jan 2011", "Mar 2012"];
我想在几个月之间“插入”,以便得到以下结果:
var sales = [5, 4, 4, 4, ..., 2, 2];
var months = ["Jan 2011", "Feb 2011", "Mar 2011", ...., "Feb 2012", "Mar 2012"];
是否有必要按顺序排列“所有可能日期的范围”数组,并列出所有需要包含的“月份+年”?或者是否有可能使用javascript不必这样做? 如何做到这一点?
注意:假设如果月份数组中没有日期,则会使用之前任何一个月的数据填充该数据。
答案 0 :(得分:2)
如果您不需要使用之前已知的销售数字,则可以使用一种不错的样条插值来表示销售数据:
/* Fritsch-Carlson monotone cubic spline interpolation
Usage example:
var f = createInterpolant([0, 1, 2, 3], [0, 1, 4, 9]);
var message = '';
for (var x = 0; x <= 3; x += 0.5) {
var xSquared = f(x);
message += x + ' squared is about ' + xSquared + '\n';
}
alert(message);
*/
var createInterpolant = function(xs, ys) {
var i, length = xs.length;
// Deal with length issues
if (length != ys.length) { throw 'Need an equal count of xs and ys.'; }
if (length === 0) { return function(x) { return 0; }; }
if (length === 1) {
// Impl: Precomputing the result prevents problems if ys is mutated later and allows garbage collection of ys
// Impl: Unary plus properly converts values to numbers
var result = +ys[0];
return function(x) { return result; };
}
// Rearrange xs and ys so that xs is sorted
var indexes = [];
for (i = 0; i < length; i++) { indexes.push(i); }
indexes.sort(function(a, b) { return xs[a] < xs[b] ? -1 : 1; });
var oldXs = xs, oldYs = ys;
// Impl: Creating new arrays also prevents problems if the input arrays are mutated later
xs = []; ys = [];
// Impl: Unary plus properly converts values to numbers
for (i = 0; i < length; i++) { xs.push(+oldXs[indexes[i]]); ys.push(+oldYs[indexes[i]]); }
// Get consecutive differences and slopes
var dys = [], dxs = [], ms = [];
for (i = 0; i < length - 1; i++) {
var dx = xs[i + 1] - xs[i], dy = ys[i + 1] - ys[i];
dxs.push(dx); dys.push(dy); ms.push(dy/dx);
}
// Get degree-1 coefficients
var c1s = [ms[0]];
for (i = 0; i < dxs.length - 1; i++) {
var m = ms[i], mNext = ms[i + 1];
if (m*mNext <= 0) {
c1s.push(0);
} else {
var dx = dxs[i], dxNext = dxs[i + 1], common = dx + dxNext;
c1s.push(3*common/((common + dxNext)/m + (common + dx)/mNext));
}
}
c1s.push(ms[ms.length - 1]);
// Get degree-2 and degree-3 coefficients
var c2s = [], c3s = [];
for (i = 0; i < c1s.length - 1; i++) {
var c1 = c1s[i], m = ms[i], invDx = 1/dxs[i], common = c1 + c1s[i + 1] - m - m;
c2s.push((m - c1 - common)*invDx); c3s.push(common*invDx*invDx);
}
// Return interpolant function
return function(x) {
// The rightmost point in the dataset should give an exact result
var i = xs.length - 1;
if (x == xs[i]) { return ys[i]; }
// Search for the interval x is in, returning the corresponding y if x is one of the original xs
var low = 0, mid, high = c3s.length - 1;
while (low <= high) {
mid = Math.floor(0.5*(low + high));
var xHere = xs[mid];
if (xHere < x) { low = mid + 1; }
else if (xHere > x) { high = mid - 1; }
else { return ys[mid]; }
}
i = Math.max(0, high);
// Interpolate
var diff = x - xs[i], diffSq = diff*diff;
return ys[i] + c1s[i]*diff + c2s[i]*diffSq + c3s[i]*diff*diffSq;
};
};
可以使用以下代码来执行您想要的操作:
var monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
var fromMonthNumber = function(monthNumber) {
return monthNames[monthNumber % 12] + ' ' + ((monthNumber / 12) | 0);
};
var toMonthNumber = function(monthName) {
var date = new Date(Date.parse(monthName));
return 12*date.getFullYear() + date.getMonth();
};
var interpolateSales = function(sales, months, range) {
var f = createInterpolant(months.map(toMonthNumber), sales);
var resultSales = [], resultMonths = [];
var firstMonth = toMonthNumber(range[0]), lastMonth = toMonthNumber(range[1]);
for (var x = firstMonth; x <= lastMonth; x++) {
resultSales.push(Math.round(f(x)));
resultMonths.push(fromMonthNumber(x));
}
return { sales: resultSales, months: resultMonths };
};
有了这个,interpolateSales([5, 4, 2], ["Jan 2011", "Apr 2011", "Feb 2012"], ["Jan 2011", "Mar 2012"])
是:
{
sales: [5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2],
months: ["Jan 2011", "Feb 2011", "Mar 2011", "Apr 2011", "May 2011", "Jun 2011", "Jul 2011", "Aug 2011", "Sep 2011", "Oct 2011", "Nov 2011", "Dec 2011", "Jan 2012", "Feb 2012", "Mar 2012"]
}