Создать массив всех целых чисел между двумя числами включительно в Javascript / jQuery [дубликат]
этот вопрос уже есть ответ здесь:
скажем, у меня есть следующие флажки:
<input type="checkbox" value="1-25" />
чтобы получить два числа, которые определяют границы диапазона, я ищу, я использую следующий вызов jQuery:
var value = $(this).val();
var lowEnd = Number(value.split('-')[0]);
var highEnd = Number(value.split('-')[1]);
как мне тогда создать массив, содержащий все целые числа между lowEnd
и highEnd
, включая lowEnd
и highEnd
сами? Для этого конкретного примера, очевидно, результирующий массив будет:
[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]
15 ответов:
в 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);
для полноты, вот он с необязательным
Я настоятельно рекомендую подчеркивание или Lo-тире библиотеки:
http://underscorejs.org/#range
(почти полностью совместим, по-видимому, lodash работает быстрее, но подчеркивание лучше doco IMHO)
_.range([start], stop, [step])
обе библиотеки имеют кучу очень полезных утилит.
моя версия цикла ;)
var lowEnd = 1; var highEnd = 25; var arr = []; while(lowEnd <= highEnd){ arr.push(lowEnd++); }
Use Case
var genArr=(1)['..'](10) //[1,2,3,4,5,6,7,8,9,10]
API;
Number.prototype['..']=function(to,step){ var arr = [],from=this; while(from <= to){ arr.push(from++); } return arr; };
скрипка :
http://jsfiddle.net/abdennour/mcpnvsmm/
ES6:
console.log( Array.from({length:10},(v,k)=>k+1) )
быстрый способ
:
- в то время как-- быстрее на большинстве браузеров
- прямая настройка переменной происходит быстрее, чем push
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--}
EDIT
читабельная версия
var arr = [], c = highEnd - lowEnd + 1; while ( c-- ) { arr[c] = highEnd-- }
демо
ДЛЯ DOWNVOTERS
производительность
http://jsperf.com/for-push-while-set/2
быстрее в ie и 3x быстрее в firefox
только на aipad air цикл for немного быстрее.
проверено на Win8, osx10.8, ubuntu14.04, для iPad, воздуха iPad, для iPod;
С chrome, ff, ie, safari, mobile safari.
Я хотел бы увидеть производительность на старых браузерах ie, где для цикла это не оптимизировано!
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);
передает разреженную матрицу в качестве списка аргументов конструктору массива, который создает плотную матрицу (фактической) длины targetLength, где все элементы имеют неопределенное значение. Первый аргумент - это значение "this" для контекста выполнения функции конструктора массива, и здесь он не играет никакой роли, и поэтому равен null.
Итак,
console.log(b);
доходность
Array [ undefined, undefined, undefined, undefined, undefined, undefined, undefined ]
наконец-то
var c = b.map(function(_, n){ return n + j; });
использует тот факт, что массив.функции карты проходит: 1. значение текущего элемента и 2. индекс текущего элемент, к делегату карты / обратному вызову. Первый аргумент отбрасывается, в то время как второй может быть использован для установки правильного значения последовательности, после корректировки на начальное смещение.
вот тут
console.log(c);
доходность
Array [ 7, 8, 9, 10, 11, 12, 13 ]
Если начало всегда меньше конца, мы можем сделать:
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.
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;
вероятно, есть более сухой способ сделать цикл, но это основная идея.
function createNumberArray(lowEnd, highEnd) { var start = lowEnd; var array = [start]; while (start < highEnd) { array.push(start); start++; } }
вы можете создать метод диапазона, который увеличивает число " от "на желаемую величину, пока не достигнет числа "до". Этот пример будет "считать" вверх или вниз, в зависимости от того, является ли 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; } }
Если вы когда-нибудь захотите перейти на десятичную сумму : массив.диапазон(0,1,.Ноль один) вам нужно будет усечь значения любой неточности с плавающей запятой. В противном случае вы вернетесь цифры 0.060000000000000005 вместо .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; } }
добавление 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 в одном фреймворке.
конечно, это не так популярны, как подчеркивать. Это может быть проблемой для некоторых.
Minified был доступен Тим Янсен с помощью лицензии CC-0 (public domain).
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; }
решения подчеркивание
data = []; _.times( highEnd, function( n ){ data.push( lowEnd ++ ) } );