有没有办法将数字列表分组为带下划线的数字区间?
// Input:
var arr = [0,1,2,8];
var interval = 3;
// Output:
// There are 3 numbers from 0 to <3
// There are 0 numbers from 3 to <6
// There is 1 number from 6 to <9
// Returns [3, 0, 1]
我注意到一些解决方案不会测试更大的值。尝试第二个测试用例:
var arr = [110,113,116,119];
答案 0 :(得分:1)
在普通的Javascript中,您可以将数字除以间隔,并使用整数部分进行分组。
使用数组和缺少间隔。
function getHistogram(array, interval) {
var bin,
result = [];
array.forEach(function (a) {
var key = Math.floor(a / interval);
if (!bin) {
bin = [key, key];
result[0] = 0;
}
while (key < bin[0]) {
--bin[0];
result.unshift(0);
}
while (key > bin[1]) {
++bin[1];
result.push(0);
}
++result[key - bin[0]];
});
return result;
}
console.log(getHistogram([0, 1, 2, 8], 3));
console.log(getHistogram([110, 113, 116, 119], 3));
console.log(getHistogram([15, 10, 26], 3));
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
使用对象和缺少间隔。
function getHistogram(array, interval) {
var bin,
result = {};
array.forEach(function (a) {
var key = Math.floor(a / interval);
if (!bin) {
bin = [key, key];
result[key] = 0;
}
while (key < bin[0]) {
result[--bin[0]] = 0;
}
while (key > bin[1]) {
result[++bin[1]] = 0;
}
++result[key];
});
return result;
}
console.log(getHistogram([0, 1, 2, 8], 3));
console.log(getHistogram([110, 113, 116, 119], 3));
console.log(getHistogram([15, 10, 26], 3));
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
答案 1 :(得分:0)
这个解决方案的想法是生成一系列直方图的X值,然后迭代数组,同时将小于每个X的值放在计数中。
var getIntervalCounts = function (arr){
// Sort backwards to iterate through in reverse later
arr.sort(function(a,b){
return b - a;
});
var interval = 3;
// Get values for range of histogram's x axis
var greatestVal = arr[0];
var leastVal = arr[arr.length-1];
var x = _.range(leastVal + interval, greatestVal + interval + 1, interval);
// Get value counts for histogram's y axis
var y = _(x).map(function(num){
var count = 0;
// Remove elements from end of array while we iterate through
// to avoid duplicate lookups
for (var i = arr.length - 1; i >= 0; i--){
// Put everything less than the histogram x in that x value
if (arr[i] < num) {
count++;
arr.pop();
} else {
break;
}
}
return count;
});
// console.log(x);
console.log(y);
}
getIntervalCounts([0,1,2,8]);
getIntervalCounts([110,111,112,118]);
getIntervalCounts([110,111,112,118,119]);
getIntervalCounts([110,111,112,118,119,120]);
<script src="http://underscorejs.org/underscore-min.js"></script>
答案 2 :(得分:0)
这是我使用普通JS的方法。我已经为您的示例添加了更多数字以便更好地进行测试。
我使用新数组来存储每个间隔中出现的次数。第一个位置代表元素的数量&lt;间隔,第二个&lt; 2 *间隔......等等。
我保留对最后一个有效索引的引用,以便我可以用零填充空单元格。
更新:在0 <= x <= 3
范围内没有值时,避免将第一个数字设为undefined
的小修补程序
// Input:
var arr = [ 110, 113, 116, 119 ],
interval = 3,
res = [],
lastIdx = -1;
arr.forEach(function(el) {
var intPart = Math.floor(el / interval),
index = el && intPart * interval === el ? intPart - 1 : intPart;
res[index] = (res[index] || 0) + 1;
res.fill(0, lastIdx + 1, index);
lastIdx = index;
});
console.log(res);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
&#13;
更新2:使用下划线的版本。它使用countBy来获取间隔并避免使用Array.prototype.fill,因为它是ES6功能。
function getZeroFilledArr(len) {
return Array.apply(null, Array(len)).map(Number.prototype.valueOf, 0);
}
function getIntervalLentgh(intervals) {
return Number(_.max(intervals)) + 1;
}
var arr = [110, 113, 116, 119],
interval = 3,
intervals = _.countBy(arr, function(el) {
var intPart = Math.floor(el / interval);
return el && intPart * interval === el ? intPart - 1 : intPart;
}),
zeroFilledArr = getZeroFilledArr(getIntervalLentgh(_.keys(intervals)));
console.log(_.reduce(intervals, function(memo, value, key) {
memo[key] = value;
return memo;
}, zeroFilledArr));
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
&#13;
答案 3 :(得分:0)
我认为这是最优雅的方式
login
_.mixin({
step: function(ar, s) {
var dummy = _.times(Math.ceil(_.max(ar)/s), function(){ return 0; });
_.each(ar, function(x) {
dummy[Math.floor(x/s)]++;
});
return dummy;
}
});
var arr = [0,1,2,4,6,7,8,9,22];
var res1 = _.step(arr, 3);
console.log("RESULT1 ", res1.length, res1);
var arr2 = [ 110, 113, 116, 119 ];
var res2 = _.step(arr2, 3);
console.log("RESULT2 ", res2.length, res2 );
以前的解决方案不考虑数组的最大值,因此不要创建结果数组的正确大小。
使用_.mixin可以为下划线定义一个可应用于数组的新函数。所以我创建了一个_.step函数,它接受数组和步骤。