自己満足なので鼻で笑ってやってください。
#概要
逆順・小数点・引数検査を意識しつつ、それなりの速度を出せたら良いな。
という想いで組んでました。
他の人のコードと比較した訳ではありませんが、今の私にはこれが限界。
幾つかコードを載せますが、やってる事はほぼ同じです。
range(from, to, step);
引数 | 変数名 | 既定値 | |
---|---|---|---|
1 | from | 0 | 起点の数値 |
2 | to | 0 | 起点からこの数値に向かう |
3 | step | 1 | 負の値は指定しない |
出力結果
//空の配列を返すパターン
console.log( range() ); //引数が空
console.log( range(-5, false) ); //第3引数までに数値以外が指定
console.log( range(-5, 5, 0) ); //stepに0が指定
//from,toが同値
console.log( range(5, 5) ); //[5]
//引数が1つ => 0に向かってstep1で生成
console.log( range(-5.5) ); //[-5.5, -4.5, -3.5, -2.5, -1.5, -0.5]
console.log( range(5.5) ); //[0.5, 1.5, 2.5, 3.5, 4.5, 5.5]
//引数が2つ => step1
console.log( range(-5, 5) ); //[-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5]
console.log( range(5, -5) ); //[5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5]
//引数が3つ => stepを指定
console.log( range(-5, 5, 2.5) ); //[-5, -2.5, 0, 2.5, 5]
console.log( range(5, -5, 2.5) ); //[5, 2.5, 0, -2.5, -5]
//4つ目以降の引数は影響なし
//負のstep値は絶対値で処理
console.log( range(-5, 5, -2, 2) ); //[-5, -3, -1, 1, 3, 5]
console.log( range(5, -5, 2, false, 2) ); //[5, 3, 1, -1, -3, -5]
#コード1
- 速度を意識したつもり
-
arguments
を使うためにアロー関数を使用しない
const range = function (from=0, to=0, step=1) {
const array = new Array();
//引数検査・調整
const argLength = 2 in arguments ? 3 : arguments.length;
for (let i = 0; i < argLength; i++) {
if (Number.isFinite(arguments[i]) === false) return array;
}
switch (argLength) {
case 0:
return array;
case 1:
if (from > 0) {
to = from;
from = from - Math.floor(from);
}
break;
case 3:
if (step === 0) return array;
step = Math.abs(step);
break;
}
//本体
if (from < to) {
for (; from <= to; from += step) array.push(from);
} else {
for (; from >= to; from -= step) array.push(from);
}
return array;
};
#コード2
- 自由に書いたもの
- コード1より遅い
const range = (...args) => { //arguments(from=0, to=0, step=1)
//引数検査・調整
args = args.slice(0, 3);
if (!args.every(Number.isFinite)) return [];
let [from=0, to=0, step=1] = args;
const comp = [
() => null,
() => from > 0 ? (to = from, from = from - Math.floor(from)) : true,
() => true,
() => step ? step = Math.abs(step) : null
];
if ( comp[args.length]() === null ) return [];
//本体
const len = Math.abs(Math.ceil((from - to) / step)) + 1;
if (from > to) step = -step;
const calc = x => from + x * step;
return [...Array(len).keys()].map(calc);
};
#コード3(ジェネレーター関数)
- コード1をジェネレーター関数に書き換えただけ
const range = function* (from=0, to=0, step=1) {
//引数検査・調整
const argLength = 2 in arguments ? 3 : arguments.length;
for (let i = 0; i < argLength; i++) {
if (Number.isFinite(arguments[i]) === false) return;
}
switch (argLength) {
case 0:
return;
case 1:
if (from > 0) {
to = from;
from = from - Math.floor(from);
}
break;
case 3:
if (step === 0) return;
step = Math.abs(step);
break;
}
//本体
if (from < to) {
for (; from <= to; from += step) yield from;
} else {
for (; from >= to; from -= step) yield from;
}
};
#最後に
うーん、色々と長い。
【javascript】一行で書かないrange関数 - Qiita
内容はこの記事の前に書いたコードなので見なくても問題ありません。