javascript javascript数组中范围之间的值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11827781/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Values between range in javascript array
提问by Hardik Mishra
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. I am getting this array from Java through JSON.
我没有开始和结束索引。我有价值观。我需要从 java 脚本数组中获取 2 个日期(最小和最大)之间的所有日期。我通过 JSON 从 Java 获取这个数组。
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 数组中获取值?
采纳答案by KooiInc
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;
}
回答by Bergi
You might use binary searchto get the indizes, then use 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. I only would use loops that result in exact indices:
然而,@Qnan 只进行一次半搜索(而不是我的三分半搜索)的方法更直接,不应有任何缺点。我只会使用导致精确索引的循环:
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);
}
回答by Qnan
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. It can be improved, of course.
这遵循@Stano 的代码,除了二进制搜索运行两次以识别更严格的边界。当然可以改进。
Here's the fiddle http://jsfiddle.net/EJsmy/1/
回答by Shanimal
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 (e.g. more recent dates)
尝试像这样优化循环(在达到 max 后打破排序列表)的问题是每次迭代时都要进行检查。在某些情况下,仅遍历整个列表会更快。特别是当您要搜索的值位于列表末尾时(例如,最近的日期)
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. Combine this with slice and the result should be optimal.
但是,如果它有所不同,您需要一个二分搜索算法。Lodash 有一个函数,它使用二进制搜索来检索将插入值的索引。将此与切片结合使用,结果应该是最佳的。
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);
}
回答by perilbrain
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;
}