简体   繁体   English

javascript数组中范围之间的值

[英]Values between range in javascript array

I have an array sorted in ascending order in java script which contains dates in milliseconds. 我有一个在java脚本中按升序排序的数组,其中包含以毫秒为单位的日期。

// Sample data; This may grow upto 1k or 2k
var dates = [1333391400000,1335292200000,1335810600000,1336329000000,1336933800000,1337020200000,
1337193000000,1337538600000,1337625000000,1337797800000,1338316200000,1338921000000,
1339093800000,1339439400000,1340303400000,1341772200000,1342463400000,1343068200000];

I don't have start and end index. 我没有开始和结束索引。 I have values. 我有价值观。 I need to get all dates between 2 dates (Min and Max) from the java script array. 我需要从java脚本数组中获取2个日期(Min和Max)之间的所有日期。 I am getting this array from Java through JSON. 我从Java通过JSON获取此数组。

Here is the method to get dates between min and max: 以下是获取最小值和最大值之间日期的方法:

function getDatesBetweenRange(min,max){
    var subArray = [];
    var value, jCntr=0;
    for(var iCntr=0;iCntr<dates.length;iCntr++){
         value = dates[iCntr];
         if(value>max)
             break;
         if(value >=min && value <=max){
             subArray[jCntr++]= value;
         }
    }
    return subArray;
}

As array is in ascending sorted order; 由于数组按升序排序; I am breaking loop if I get max value than the provided max value in the argument. 如果我得到的最大值超过参数中提供的最大值,我就会打破循环。

Is there any other efficient way to get values from Java Script array ? 有没有其他有效的方法从Java Script数组中获取值?

Here's a semi binary filter method that seems more efficient (at least in my browsers - Chrome, Firefox, IE9) 这是一个看似更有效的半二进制过滤方法(至少在我的浏览器中 - Chrome,Firefox,IE9)

function filterBinary(arr,min,max){
 var len   = arr.length
    ,up    = -1
    ,down  = len
    ,rrange= []
    ,mid   = Math.floor(len/2) 
 ;
 while (up++<mid && down-->mid){
    if (arr[up]>=max || arr[down]<=min){break;}
    if (arr[up]>=min){
      rrange.push(arr[up]);
    }
    if (arr[down]<=max){
      rrange.push(arr[down]);
    }
 }
 return rrange;   
}

You might use binary search to get the indizes, then use slice : 您可以使用二进制搜索来获取indizes,然后使用slice

Array.prototype.sliceRange = function(min, max) {
    if (min > max) return this.sliceRange(max, min);
    var l = 0,
        r = this.length;
    // find an element at index m that is in range
    rough: {
        while (l < r) {
            var m = Math.floor(l + (r - l) / 2);
            if (this[m] < min)
                l = m + 1;
            else if (this[m] > max)
                r = m;
            else
                break rough;
        }
        // l == r: none was found
        return [];
    }
    var lr = m, // right boundary for left search
        rl = m; // left boundary for right search
    // get first position of items in range (l == lr)
    while (l < lr) {
        m = Math.floor(l + (lr - l) / 2);
        if (this[m] < min)
            l = m + 1;
        else
            lr = m;
    }
    // get last position of items in range (r == rl)
    while (rl < r) {
        m = Math.floor(rl + (r - rl) / 2);
        if (this[m] > max)
            r = m;
        else
            rl = m + 1;
    }
    // return the items in range
    return this.slice(l, r);
}

( Demo ) 演示


Yet, @Qnan's approach to do only one and a half searches (instead of my three half searches) is more straightforward and should not suffer any disadvantages. 然而,@ Qnan只进行一次半搜索(而不是我的三次搜索)的方法更直接,不应该有任何缺点。 I only would use loops that result in exact indices: 我只会使用导致精确索引的循环:

Array.prototype.sliceRange = function(min, max) {
    if (min > max) return this.sliceRange(max, min);
    var l = 0,
        c = this.length,
        r = c;
    // get first position of items in range (l == c)
    while (l < c) {
        var m = Math.floor(l + (c - l) / 2);
        if (this[m] < min)
            l = m + 1;
        else
            c = m;
    }
    // get last position of items in range (c == r)
    while (c < r) {
        var m = Math.floor(c + (r - c) / 2);
        if (this[m] > max)
            r = m;
        else
            c = m + 1;
    }
    // return the items in range
    return this.slice(l, r);
}

Here's roughly what the binary search would look like in this case 这里大致是二进制搜索在这种情况下的样子

var dates = [1333391400000,1335292200000,1335810600000,1336329000000,1336933800000,1337020200000,
1337193000000,1337538600000,1337625000000,1337797800000,1338316200000,1338921000000,
1339093800000,1339439400000,1340303400000,1341772200000,1342463400000,1343068200000];

function getDatesBetweenRange(min, max) {
    var subArray = [];
    var value, iCntr;
    var start, end;

    var low = 0, high = dates.length - 1;
    while (high - low > 1) {
        centre = Math.floor((high + low) / 2);
        if (dates[centre] < min)
            low = centre;
        else 
            high = centre;
    }
    start = low;
    high = dates.length - 1
    while (high - low > 1) {
        centre = Math.floor((high + low) / 2);
        if (dates[centre] > max)
            high = centre;
        else 
            low = centre;
    }
    end = high;

    for (var i = start; i < end; i++) {
        value = dates[i];
        if (value < min) {
            continue;
        }
        if (value > max) {
            break;
        }
        subArray.push(value);
    }
    return subArray;
}

console.log(getDatesBetweenRange(1337193000000, 1337797800000));​

This follows the code by @Stano, except that binary search is ran twice to identify the tighter bounds. 这遵循@Stano的代码,除了二次搜索运行两次以识别更严格的边界。 It can be improved, of course. 当然,它可以改进。

Here's the fiddle http://jsfiddle.net/EJsmy/1/ 这是小提琴http://jsfiddle.net/EJsmy/1/

The problem with trying to optimize the loop like this (breaking out of the sorted list after max is reached) is that you are doing a check each time you iterate. 试图像这样优化循环的问题(在达到最大值后突破排序列表)是每次迭代时都要进行检查。 Its faster in some cases to just iterate through the entire list. 在某些情况下,它可以更快地遍历整个列表。 Particularly when the values you are searching for are at the end of the list (eg more recent dates) 特别是当您搜索的值位于列表的末尾时(例如,最近的日期)

But, if it makes a difference you need a binary search algorithm. 但是,如果它有所作为,你需要一个二进制搜索算法。 Lodash has a function that uses a binary search to retrieve the index where a value would be inserted. Lodash有一个函数,它使用二进制搜索来检索将插入值的索引。 Combine this with slice and the result should be optimal. 将其与切片结合使用,结果应该是最佳的。

Using [Lodash][1] 使用[Lodash] [1]

// sliced :  get all values between+including min-max from sorted array of numbers
// @param array sorted timestamps
// @param min timestamp minimum
// @param max timestamp maximum
function sliced(array,min,max){
    return array.slice(_.sortedIndex(array, min),_.sortedIndex(array, max)+1);
}
  function getDatesBetweenRange(min,max)
    {   
      var subArray = dates.slice(0,dates.length-1);

      for(var iCntr=0;iCntr<dates.length;iCntr++)
       {
       if(!(dates[iCntr] >=min && dates[iCntr] <=max))
          {
             subArray.splice(iCntr,1); 
          }
        }
       return subArray; 
   } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM