检查数组中的值是否在一个范围内

时间:2014-05-21 22:59:07

标签: javascript jquery

我需要检查我所拥有的数组是否在某个范围内。

我有一个数组:

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}

5 个答案:

答案 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)

完全小提琴:http://jsfiddle.net/6RRyL/1/

答案 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 ] } ]

http://jsbin.com/fowop/1/edit

使用该数据,您可以执行所需操作,例如获取最大值:

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);

Demo.

请注意,我向数组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