【问题标题】:Create array of all integers between two numbers, inclusive, in Javascript/jQuery在Javascript / jQuery中创建两个数字之间的所有整数的数组,包括在内
【发布时间】:2011-12-25 12:58:34
【问题描述】:

假设我有以下复选框:

<input type="checkbox" value="1-25" />

要获得定义我正在寻找的范围边界的两个数字,我使用以下 jQuery:

var value = $(this).val();
var lowEnd = Number(value.split('-')[0]);
var highEnd = Number(value.split('-')[1]);

然后如何创建一个包含lowEndhighEnd 之间的所有整数的数组,包括lowEndhighEnd 本身?对于这个特定的示例,显然,结果数组将是:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]

【问题讨论】:

  • 没什么值得注意的。创建数组是我一直试图解决的一个更大问题的一部分,我一直在从一个完全不同的方向着手。我意识到这可能是一种更有效的方法,尽管事实上数组是 JS 的一个元素,但我一直难以完全掌握。不幸的是,我在 Stack Overflow 或其他地方找不到专门处理这个问题的任何东西。
  • 重复的问题不一样。被骗的 Q 只是简单地创建一个范围,而这个问题要求在两个预先确定的变量之间创建一个范围。其他问题中的大多数答案都不能解决这个问题,因为您不能使用变量(例如Array.from())。

标签: javascript jquery arrays


【解决方案1】:
var list = [];
for (var i = lowEnd; i <= highEnd; i++) {
    list.push(i);
}

【讨论】:

  • 只是为了一般信息,在 CoffeeScript 中它看起来像“1..25”,实际上在 JavaScript 中转换为类似这样的东西。所以没有更简单的方法可以做到这一点。
  • @FreeCandies - 的确,CoffeeScript 具有这种便利性,但您仍然必须通过编译器运行它 - 速度慢或不方便,而且您对如何手动操作一无所知。我真诚地希望我们不要用“只使用 CoffeeScript”来取代“只使用 jQuery”的时代
  • 注意,正确的coffeescript表示法是[1..25]
【解决方案2】:

ES6:

使用 Array.from(文档here):

console.log(
   Array.from({length:5},(v,k)=>k+1)
)

【讨论】:

【解决方案3】:

在 JavaScript ES6 中:

function range(start, end) {
  return Array(end - start + 1).fill().map((_, idx) => start + idx)
}
var result = range(9, 18); // [9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
console.log(result);

为了完整起见,这里有一个可选的step 参数。

function range(start, end, step = 1) {
  const len = Math.floor((end - start) / step) + 1
  return Array(len).fill().map((_, idx) => start + (idx * step))
}
var result = range(9, 18, 0.83);
console.log(result);

我会在实际项目中使用npm 中的range-inclusive。它甚至支持倒退,这很酷。

【讨论】:

  • 太糟糕了fill() 不支持移动浏览器(目前)。
  • 到目前为止,我可以确认它在 Android WebView 中运行(Android System WebView 60.0.3112.116Android 6.0.1Nexus 5
  • Array.from({length:256},(v,k)=>k++) 更好:D
【解决方案4】:

我强烈推荐 underscore 或 lo-dash 库:

http://underscorejs.org/#range

(几乎完全兼容,显然 lodash 运行速度更快,但下划线具有更好的 doco 恕我直言)

_.range([start], stop, [step])

这两个库都有很多非常有用的实用程序。

【讨论】:

  • ramda 也有一个方便的版本。
【解决方案5】:

我的循环版本;)

var lowEnd = 1;
var highEnd = 25;
var arr = [];
while(lowEnd <= highEnd){
   arr.push(lowEnd++);
}

【讨论】:

  • 这种方法的性能大大优于选择的答案,仅供参考。
  • 如果使用var arr = new Array(highEnd - lowEnd + 1)会快几倍。
【解决方案6】:

最快的方式

  1. while-- 在大多数浏览器上更快
  2. 直接设置变量比推送更快

功能:

var x=function(a,b,c,d){d=[];c=b-a+1;while(c--){d[c]=b--}return d},

theArray=x(lowEnd,highEnd);

var arr=[],c=highEnd-lowEnd+1;
while(c--){arr[c]=highEnd--}

编辑

可读版本

var arr = [],
c = highEnd - lowEnd + 1;
while ( c-- ) {
 arr[c] = highEnd--
}

演示

http://jsfiddle.net/W3CUn/

对于反对者

性能

http://jsperf.com/for-push-while-set/2

在 ie 中更快,在 firefox 中快 3 倍

只有在 aipad air 上,for 循环要快一些。

在win8、osx10.8、ubuntu14.04、ipad、ipad air、ipod上测试;

使用 chrome,ff,ie,safari,mobile safari。

我想看看 for 循环没有优化的旧 ie 浏览器的性能!

【讨论】:

  • 这些想法很棒...但我会尝试通过适当的缩进、字间距和换行让您的代码更容易被其他人阅读...
  • 因为这是非常短的函数,没有多少参数,我打算这样写,所以你可以复制和过去。在第一种情况下,只需用你想要的任何函数名称替换 x。也不需要更改函数 abcd,因为它们只是函数私有参数。
  • 并将 c & d 放在函数参数中作为占位符以省略 'var'
【解决方案7】:
function range(j, k) { 
    return Array
        .apply(null, Array((k - j) + 1))
        .map(function(_, n){ return n + j; }); 
}

这大致相当于

function range(j, k) { 
    var targetLength = (k - j) + 1;
    var a = Array(targetLength);
    var b = Array.apply(null, a);
    var c = b.map(function(_, n){ return n + j; });
    return c;
}

分解:

var targetLength = (k - j) + 1;

var a = Array(targetLength);

这会创建一个具有正确标称长度的稀疏矩阵。现在稀疏矩阵的问题是,虽然它有正确的标称长度,但它没有实际元素,所以,对于

j = 7, k = 13

console.log(a);

给我们

Array [ <7 empty slots> ]

然后

var b = Array.apply(null, a);

将稀疏矩阵作为参数列表传递给 Array 构造函数,该构造函数生成(实际)长度为 targetLength 的密集矩阵,其中所有元素都有未定义的值。第一个参数是数组构造函数执行上下文的'this'值,在这里没有任何作用,null也是。

现在,

 console.log(b);

产量

 Array [ undefined, undefined, undefined, undefined, undefined, undefined, undefined ]

终于

var c = b.map(function(_, n){ return n + j; });

利用 Array.map 函数传递的事实: 1. 当前元素的值和 2. 当前元素的索引,到映射委托/回调。第一个参数被丢弃,而第二个参数在调整起始偏移后可用于设置正确的序列值。

那么

console.log(c);

产量

 Array [ 7, 8, 9, 10, 11, 12, 13 ]

【讨论】:

  • 感谢您发布此问题的答案!在 Stack Overflow 上不鼓励仅使用代码的答案,因为原始发布者(或未来的读者)可能难以理解它们背后的逻辑。请编辑您的问题并包含对您的代码的解释,以便其他人可以从您的回答中受益。谢谢!
  • @MaximillianLaumeister 注释
  • 这是一个很好的答案!
  • 只是一个建议,但“_”(下划线)似乎是丢弃/未使用参数的通用名称。
【解决方案8】:

我的五分钱:

双向整数数组函数。

range(0, 5)变成[0, 1, 2, 3, 4, 5]

range(5, 0) 变为 [5, 4, 3, 2, 1, 0]

基于this 的回答。

function range(start, end) {
  const isReverse = (start > end);
  const targetLength = isReverse ? (start - end) + 1 : (end - start ) + 1;
  const arr = new Array(targetLength);
  const b = Array.apply(null, arr);
  const result = b.map((discard, n) => {
    return (isReverse) ? n + end : n + start;
  });

  return (isReverse) ? result.reverse() : result;
}

附:为了在现实生活中使用,您还应该检查 isFinite()isNaN() 的参数。

【讨论】:

    【解决方案9】:
    function createNumberArray(lowEnd, highEnd) {
        var start = lowEnd;
        var array = [start];
        while (start < highEnd) {
            array.push(start);
            start++;
        }
    } 
    

    【讨论】:

    • var array = {start}; 为您提供了一个没有 push 方法的标准对象。你的意思是var array = [];当然
    【解决方案10】:

    如果开始总是小于结束,我们可以这样做:

    function range(start, end) {
      var myArray = [];
      for (var i = start; i <= end; i += 1) {
        myArray.push(i);
      }
      return myArray;
    };
    console.log(range(4, 12));                 // → [4, 5, 6, 7, 8, 9, 10, 11, 12]
    

    如果我们希望能够采用第三个参数来修改用于构建数组的步骤,并使其即使开始大于结束也可以工作:

    function otherRange(start, end, step) {
      otherArray = [];
      if (step == undefined) {
        step = 1;
      };
      if (step > 0) {
        for (var i = start; i <= end; i += step) {
          otherArray.push(i);
        }
      } else {
        for (var i = start; i >= end; i += step) {
          otherArray.push(i);
        }
      };
      return otherArray;
    };
    console.log(otherRange(10, 0, -2));        // → [10, 8, 6, 4, 2, 0]
    console.log(otherRange(10, 15));           // → [10, 11, 12, 13, 14, 15]
    console.log(otherRange(10, 20, 2));        // → [10, 12, 14, 16, 18, 20]
    

    这样函数接受正负步长,如果没有给出步长,则默认为1。

    【讨论】:

      【解决方案11】:
      var values = $(this).val().split('-'),
          i = +values[0],
          l = +values[1],
          range = [];
      
      while (i < l) {
          range[range.length] = i;
          i += 1;
      }
      
      range[range.length] = l;
      

      可能有一种 DRYer 方法来执行循环,但这是基本思想。

      【讨论】:

        【解决方案12】:

        您可以设计一个 range 方法,将“from”数字增加所需的数量,直到达到“to”数字。 此示例将向上或向下“计数”,具体取决于 from 大于还是小于 to。

        Array.range= function(from, to, step){
            if(typeof from== 'number'){
                var A= [from];
                step= typeof step== 'number'? Math.abs(step):1;
                if(from> to){
                    while((from -= step)>= to) A.push(from);
                }
                else{
                    while((from += step)<= to) A.push(from);
                }
                return A;
            }   
        }
        

        如果你想步进小数:Array.range(0,1,.01) 您将需要截断任何浮点不精确的值。 否则你会返回像 0.060000000000000005 而不是 0.06。

        这比其他版本增加了一点开销,但对于整数或小数步长来说可以正常工作。

        Array.range= function(from, to, step, prec){
            if(typeof from== 'number'){
                var A= [from];
                step= typeof step== 'number'? Math.abs(step):1;
                if(!prec){
                    prec= (from+step)%1? String((from+step)%1).length+1:0;
                }
                if(from> to){
                    while(+(from -= step).toFixed(prec)>= to) A.push(+from.toFixed(prec));
                }
                else{
                    while(+(from += step).toFixed(prec)<= to) A.push(+from.toFixed(prec));
                }
                return A;
            }   
        }
        

        【讨论】:

          【解决方案13】:

          http://minifiedjs.com/ 添加到答案列表中:)

          代码类似于下划线等:

          var l123 = _.range(1, 4);      // same as _(1, 2, 3)
          var l0123 = _.range(3);        // same as _(0, 1, 2)
          var neg123 = _.range(-3, 0);   // same as _(-3, -2, -1)
          var empty = _.range(2,1);      // same as _()
          

          这里的文档: http://minifiedjs.com/api/range.html

          我使用 minified.js 是因为它解决了我的所有问题,占用空间小且语法易于理解。对我来说,它是一个框架中 jQuery、MustacheJS 和 Underscore/SugarJS 的替代品。

          当然,它不像下划线那么流行。这可能是一些人担心的问题。

          Tim Jansen 使用 CC-0(公共领域)许可证提供了 Minified。

          【讨论】:

            【解决方案14】:
            const range = (start, stop, step) => Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step));
            

            来源:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from

            【讨论】:

              【解决方案15】:
              _Array = (length) => Object.keys(Array.from({length}))
              
              //_Array = [0, 1, 2, 3, 4]
              

              【讨论】:

              • 这与采用类似方法的其他答案有何不同?
              【解决方案16】:

              解决underscore

              data = [];
              _.times( highEnd, function( n ){ data.push( lowEnd ++ ) } );
              

              【讨论】:

                【解决方案17】:

                        function getRange(a,b)
                        {
                            ar = new Array();
                            var y = a - b > 0 ? a - b : b - a;
                            for (i=1;i<y;i++)
                            {
                                ar.push(i+b);
                            }
                            return ar;
                        }

                【讨论】:

                • 这实际上会为 a > b 产生不正确的结果,例如getRange (5, 1) - 它会产生 [1,2,3,4,5] 但应该是 [5,4,3,2,1]
                猜你喜欢
                • 2015-07-12
                • 1970-01-01
                • 2021-01-28
                • 1970-01-01
                • 1970-01-01
                • 2012-04-25
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多