我需要检查我所拥有的数组是否在某个范围内。
我有一个数组:
var times = [79, 118, 145, 245, 688, 833, 934, 956, 1019, -339, -324, -265, 65, 81, 83, 121, 151, 154, 359]
并希望得到落在这些范围内的值的数量:
var ranges = ['0-10', '11-20', '21-30', '31-40', '41-50', '51-60', '61 +'];
这是我到目前为止的代码..
$.each(times, function (i, datum)
{
if (datum <= 0)
sum1 += 1;
else if (datum > 10 && datum <= 20)
sum2 += 1;
else if (datum > 20 && datum <= 30)
sum3 += 1;
else if (datum > 30 && datum <= 40)
sum4 += 1;
else if (datum > 40 && datum <= 50)
sum5 += 1;
else if (datum > 50 && datum <= 60)
sum6 += 1;
else if (datum > 60)
sum7 += 1;
}
我如何获得范围和总和的对象。例如{'0-10':2,'11 -20':19,'21 -30':45}
答案 0 :(得分:1)
var times = [79, 118, 145, 245, 688, 833, 934, 956, 1019, -339, -324, -265, 65, 81, 83, 121, 151, 154, 359];
var ranges = ['0-10', '11-20', '21-30', '31-40', '41-50', '51-60', '61 +'];
function getObj(range){
var obj={};
range=range.replace("+","-Infinity");
var arr=range.split("-");
return {sum:0,min:Number(arr[0]),max:Number(arr[1])};
}
var sums={};
for(var i=0;i<ranges.length;i++) sums[ranges[i]]=getObj(ranges[i]);
for(var i=0;i<times.length;i++){
for(var j=0;j<ranges.length;j++){
var sum=sums[ranges[j]];
if(times[i]>=sum.min && times[i] <= sum.max){sum.sum+=1}
}
}
console.log(sums)
答案 1 :(得分:1)
我建议输出一个集合,而不是一个对象,因为它更容易使用;因为它是一个可以过滤,映射和缩小的对象数组,您无法在对象上做得非常舒服。例如:
function getStepRanges(ranges, times) {
return ranges.map(function(range) {
var ranges = range.split(/[-+]/)
var min = +ranges[0]
var max = +ranges[1] || Infinity
return times.reduce(function(acc, x) {
// Note that your range is not inclusive
// you may want to do "x >= min" instead
if (x > min && x <= max) {
acc.range = range
acc.values = (acc.values||[]).concat(x)
}
return acc
},{})
})
}
在这个虚拟数据上使用它:
var times = [1,2,3,4,5,10,11,12,13,14,21,23,24,25,26,31,32,33,34,35,41,42,43,44,45,51,52,53,54,55,61,62,63]
var ranges = ['0-10', '11-20', '21-30', '31-40', '41-50', '51-60', '61+']
它将返回此集合:
[ { range: '0-10', values: [ 1, 2, 3, 4, 5, 10 ] },
{ range: '11-20', values: [ 12, 13, 14 ] },
{ range: '21-30', values: [ 23, 24, 25, 26 ] },
{ range: '31-40', values: [ 32, 33, 34, 35 ] },
{ range: '41-50', values: [ 42, 43, 44, 45 ] },
{ range: '51-60', values: [ 52, 53, 54, 55 ] },
{ range: '61+', values: [ 62, 63 ] } ]
使用该数据,您可以执行所需操作,例如获取最大值:
var result = getStepRanges(ranges, times)
// Easy, we have a collection!
// but careful, it mutates the original object
// you may want to use an "extend" helper to clone it first
var maxRanges = result.map(function(x) {
x.max = Math.max.apply(0, x.values)
return x
})
console.log(maxRanges)
/*[ { range: '0-10', values: [ 1, 2, 3, 4, 5, 10 ], max: 10 },
{ range: '11-20', values: [ 12, 13, 14 ], max: 14 },
{ range: '21-30', values: [ 23, 24, 25, 26 ], max: 26 },
{ range: '31-40', values: [ 32, 33, 34, 35 ], max: 35 },
{ range: '41-50', values: [ 42, 43, 44, 45 ], max: 45 },
{ range: '51-60', values: [ 52, 53, 54, 55 ], max: 55 },
{ range: '61+', values: [ 62, 63 ], max: 63 } ]*/
答案 2 :(得分:0)
假设您重写范围:
rangeList = $.map(ranges, function(item) {
values = item.split('-')
return {min: parseInt(values[0]), max: parseInt(values[1]) || Number.POSITIVE_INFINITY, label: item}
})
你有一个很好的结构。现在,您必须针对每个范围测试每个值。 (从技术上讲,你可以在第一个匹配时停止,所以你可以使用any
代替each
,如果满足范围则返回true。
var sums = {}
$.each(times, function(i, datum) {
$.each(rangeList, function(rangeIndex, range) {
if (datum > range.min && datum <= range.max) {
sums[range.label] = (sums[range.label] || 0) + 1
}
})
})
当然,在您的情况下,返回{61 +: 16}
答案 3 :(得分:0)
如果没有Underscore答案,那么答案就不会完整:
var times = [79, 118, 145, 245, 688, 833, 934, 956, 1019, -339, -324, -265, 65, 81, 83, 121, 151, 154, 359]
var ranges = ['0-10', '11-20', '21-30', '31-40', '41-50', '51-60', '61 +'];
var counts = _(ranges).reduce(function(memo, range) {
memo[range] = 0;
return memo;
}, {});
counts.outOfBounds = 0;
var rangePattern = /(\d+)\s*-\s*(\d+)/;
var moreThanPattern = /(\d+)\s*\+/;
var lessThanPattern = /-\s*(\d+)/;
_(times).forEach(function(value) {
var range = _(ranges).find(function(testRange) {
var match;
switch (false) {
case !(match = testRange.match(rangePattern)):
return (value >= match[1] && value <= match[2]);
case !(match = testRange.match(moreThanPattern)):
return (value >= match[1]);
case !(match = testRange.match(lessThanPattern)):
return (value <= match[1]);
default:
return false;
}
});
counts[range || 'outOfBounds']++;
});
console.log(counts);
在此JSBin
中查看此操作答案 4 :(得分:0)
您可以尝试以下代码:
var times = [79, 118, 145, 245, 688, 833, 15, 934, 956, 1019, -339, -324, -265, 65, 81, 83, 121, 151, 154, 359];
var ranges = ['0-10', '11-20', '21-30', '31-40', '41-50', '51-60', '61 +'];
var rangeStops = [0,11,21,31,41,51,61];
var rangeCounts = [0];
//sort the times first
times.sort(function(a,b){return a - b});
var k = 0;
for(var i = 0; i < times.length; i++){
if(rangeStops[k] > times[i]) continue;
else if(rangeStops[k+1] <= times[i]&&k != rangeStops.length - 1){
rangeCounts[++k] = 0;
i--;
} else rangeCounts[k]++;
}
//output
ranges = ranges.map(function(e,i){
var result = {};
result[e] = rangeCounts[i];
return result;
});
//log it and see the result in console window
console.log(ranges);
请注意,我向数组15
添加了times
值,结果应为:
'0-10': 0
'11-20': 1 //the 15 value
'21-30': 0
'31-40': 0
'41-50': 0
'51-60': 0
'61+' : 16 //all the other positive values