보다 큼 /보다 큼에 대한 스위치 설명
그래서 다음과 같이 switch 문을 사용하고 싶습니다.
switch (scrollLeft) {
case (<1000):
//do stuff
break;
case (>1000 && <2000):
//do stuff
break;
}
이제 나는 그 진술 ( <1000
) 또는 ( >1000 && <2000
) 중 하나가 작동하지 않는다는 것을 알고 있습니다 (확실히 다른 이유로). 내가 묻는 것은 그 일을하는 가장 효율적인 방법입니다. 나는 30 개의 if
문장을 사용하는 것을 싫어 하므로 스위치 구문을 사용하고 싶습니다. 내가 할 수있는 일이 있습니까?
다른 답변의 솔루션을 볼 때 성능이 좋지 않은 것을 알았습니다. 나는 그것들을 의견에 넣을 것이지만 그것을 벤치마킹하고 결과를 공유하는 것이 더 낫다고 생각했다. 직접 테스트 할 수 있습니다 . 아래는 각 브라우저에서 가장 빠른 작업 후 표준화 된 결과 (ymmv)입니다 (1.0 시간에 정규화 된 값을 곱하여 절대 시간 (ms)).
Chrome Firefox Opera MSIE Safari 노드 -------------------------------------------------- ----------------- 1.0 시간 37ms 73ms 68ms 184ms 73ms 21ms 즉각적인 경우 1.0 1.0 1.0 2.6 1.0 1.0 간접적 인 경우 1.2 1.8 3.3 3.8 2.6 1.0 스위치 즉시 2.0 1.1 2.0 1.0 2.8 1.3 스위치 범위 38.1 10.6 2.6 7.3 20.9 10.4 스위치 범위 2 31.9 8.3 2.0 4.5 9.5 6.9 스위치 간접 어레이 35.2 9.6 4.2 5.5 10.7 8.6 어레이 선형 스위치 3.6 4.1 4.5 10.0 4.7 2.7 어레이 이진 스위치 7.8 6.7 9.5 16.0 15.0 4.9
Chrome 21.0.1180.89m , Firefox 15.0 , Opera 12.02 , MSIE 9.0.8112 , Safari 5.1.7 과 같은 버전으로 Windows 7 32 비트에서 수행되는 위치에서 테스트하십시오 . Windows 용 Node.js의 타이머 해상도가 1ms가 아니라 10ms이므로 Linux 64 비트 상자에서 노드 가 실행되었습니다.
즉시
이것은 드럼 롤 MSIE를 제외하고 모든 테스트 된 환경에서 가장 빠릅니다 ! (놀람, 놀라움). 이를 구현하기 위해 권장되는 방법입니다.
if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else
간접적 인 경우
이것은 -statement를 대신 한 변형 switch-indirect-array
이지만 거의 모든 테스트 된 환경에서 if
보다 훨씬 빠르게 수행 switch-indirect-array
됩니다.
values=[
1000, 2000, ... 30000
];
if (val < values[0]) { /* do something */ } else
if (val < values[1]) { /* do something */ } else
...
if (val < values[29]) { /* do something */ } else
스위치 즉시
이것은 테스트 된 모든 환경에서 매우 빠르며 실제로 MSIE에서 가장 빠릅니다. 계산을 수행하여 색인을 얻을 수있을 때 작동합니다.
switch (Math.floor(val/1000)) {
case 0: /* do something */ break;
case 1: /* do something */ break;
...
case 29: /* do something */ break;
}
스위치 범위
이는 약 1.5 배의 시간이 걸리는 Opera를 제외하고는 모든 테스트 된 환경에서 가장 빠른 것보다 약 6 ~ 40 배 느립니다. 엔진이 각 경우에 대해 값을 두 번 비교해야하기 때문에 속도가 느립니다. 놀랍게도 Chrome에서 가장 빠른 작업에 비해 Chrome을 완료하는 데 거의 40 배가 더 걸리지 만 MSIE는 6 배만 걸립니다. 그러나 실제 시차는 1337ms (!)에서 MSIE에 유리한 74ms에 불과했습니다.
switch (true) {
case (0 <= val && val < 1000): /* do something */ break;
case (1000 <= val && val < 2000): /* do something */ break;
...
case (29000 <= val && val < 30000): /* do something */ break;
}
스위치 범위 2
이는 switch-range
사례 당 하나의 비교 만 있는 변형 이지만 더 빠르지 만 Opera를 제외하고는 여전히 매우 느립니다. 엔진이 소스 코드 순서로 각 사례를 테스트하므로 사례 설명의 순서는 중요합니다 . ECMAScript262 : 5 12.11
switch (true) {
case (val < 1000): /* do something */ break;
case (val < 2000): /* do something */ break;
...
case (val < 30000): /* do something */ break;
}
스위치 간접 배열
이 변형에서 범위는 배열에 저장됩니다. 테스트 된 모든 환경에서 느리고 Chrome에서는 매우 느립니다.
values=[1000, 2000 ... 29000, 30000];
switch(true) {
case (val < values[0]): /* do something */ break;
case (val < values[1]): /* do something */ break;
...
case (val < values[29]): /* do something */ break;
}
배열 선형 검색
이것은 배열에서 값의 선형 검색과 고정 값을 가진 switch 문의 조합입니다. 이것을 사용하려는 이유는 런타임까지 값을 알 수 없기 때문입니다. 테스트 된 모든 환경에서 속도가 느리고 MSIE에서 거의 10 배의 시간이 걸립니다.
values=[1000, 2000 ... 29000, 30000];
for (sidx=0, slen=values.length; sidx < slen; ++sidx) {
if (val < values[sidx]) break;
}
switch (sidx) {
case 0: /* do something */ break;
case 1: /* do something */ break;
...
case 29: /* do something */ break;
}
어레이 이진 스위치
This is a variant of array-linear-switch
but with a binary search. Unfortunately it is slower than the linear search. I don't know if it is my implementation or if the linear search is more optimized. It could also be that the keyspace is to small.
values=[0, 1000, 2000 ... 29000, 30000];
while(range) {
range = Math.floor( (smax - smin) / 2 );
sidx = smin + range;
if ( val < values[sidx] ) { smax = sidx; } else { smin = sidx; }
}
switch (sidx) {
case 0: /* do something */ break;
...
case 29: /* do something */ break;
}
Conclusion
If performance is important, use if
-statements or switch
with immediate values.
An alternative:
var scrollleft = 1000;
switch (true)
{
case (scrollleft > 1000):
alert('gt');
break;
case (scrollleft <= 1000):
alert('lt');
break;
}
Demo: http://jsfiddle.net/UWYzr/
switch (Math.floor(scrollLeft/1000)) {
case 0: // (<1000)
//do stuff
break;
case 1: // (>=1000 && <2000)
//do stuff;
break;
}
Only works if you have regular steps...
EDIT: since this solution keeps getting upvotes, I must advice that mofolo's solution is a way better
You can create a custom object with the criteria and the function corresponding to the criteria
var rules = [{ lowerLimit: 0, upperLimit: 1000, action: function1 },
{ lowerLimit: 1000, upperLimit: 2000, action: function2 },
{ lowerLimit: 2000, upperLimit: 3000, action: function3 }];
Define functions for what you want to do in these cases (define function1, function2 etc)
And "evaluate" the rules
function applyRules(scrollLeft)
{
for(var i=0; i>rules.length; i++)
{
var oneRule = rules[i];
if(scrollLeft > oneRule.lowerLimit && scrollLeft < oneRule.upperLimit)
{
oneRule.action();
}
}
}
Note
I hate using 30 if statements
Many times if statements are easier to read and maintain. I would recommend the above only when you have a lot of conditions and a possibility of lot of growth in the future.
Update
As @Brad pointed out in the comments, if the conditions are mutually exclusive (only one of them can be true at a time), checking the upper limit should be sufficient:
if(scrollLeft < oneRule.upperLimit)
provided that the conditions are defined in ascending order (first the lowest one, 0 to 1000
, and then 1000 to 2000
for example)
What exactly are you doing in //do stuff
?
You may be able to do something like:
(scrollLeft < 1000) ? //do stuff
: (scrollLeft > 1000 && scrollLeft < 2000) ? //do stuff
: (scrollLeft > 2000) ? //do stuff
: //etc.
Untested and unsure if this will work, but why not do a few if statements
before, to set variables for the switch statement
.
var small, big;
if(scrollLeft < 1000){
//add some token to the page
//call it small
}
switch (//reference token/) {
case (small):
//do stuff
break;
case (big):
//do stuff;
break;
}
This is another option:
switch (true) {
case (value > 100):
//do stuff
break;
case (value <= 100)&&(value > 75):
//do stuff
break;
case (value < 50):
//do stuff
break;
}
Updating the accepted answer (can't comment yet). As of 1/12/16 using the demo jsfiddle in chrome, switch-immediate is the fastest solution.
Results: Time resolution: 1.33
25ms "if-immediate" 150878146
29ms "if-indirect" 150878146
24ms "switch-immediate" 150878146
128ms "switch-range" 150878146
45ms "switch-range2" 150878146
47ms "switch-indirect-array" 150878146
43ms "array-linear-switch" 150878146
72ms "array-binary-switch" 150878146
Finished
1.04 ( 25ms) if-immediate
1.21 ( 29ms) if-indirect
1.00 ( 24ms) switch-immediate
5.33 ( 128ms) switch-range
1.88 ( 45ms) switch-range2
1.96 ( 47ms) switch-indirect-array
1.79 ( 43ms) array-linear-switch
3.00 ( 72ms) array-binary-switch
In my case (color-coding a percentage, nothing performance-critical), I quickly wrote this:
function findColor(progress) {
const thresholds = [30, 60];
const colors = ["#90B451", "#F9A92F", "#90B451"];
return colors.find((col, index) => {
return index >= thresholds.length || progress < thresholds[index];
});
}
I hate using 30 if statements
I had the same situation lately, that's how I solved it:
before:
if(wind_speed >= 18) {
scale = 5;
} else if(wind_speed >= 12) {
scale = 4;
} else if(wind_speed >= 9) {
scale = 3;
} else if(wind_speed >= 6) {
scale = 2;
} else if(wind_speed >= 4) {
scale = 1;
}
after:
var scales = [[4, 1], [6, 2], [9, 3], [12, 4], [18, 5]];
scales.forEach(function(el){if(wind_speed > el[0]) scale = el[1]});
And if you set "1, 2, 3, 4, 5" then it can be even simpler:
var scales = [4, 6, 9, 12, 18];
scales.forEach(function(el){if(wind_speed >= el) scale++});
참고URL : https://stackoverflow.com/questions/6665997/switch-statement-for-greater-than-less-than
'Programing' 카테고리의 다른 글
Linux 명령 행을 사용하여 Node.JS를 설치 제거 하시겠습니까? (0) | 2020.05.01 |
---|---|
누군가 SQL 쿼리를 저작권으로 보호 할 수 있습니까? (0) | 2020.05.01 |
5 살짜리에게 의존성 주입을 설명하는 방법? (0) | 2020.05.01 |
Windows를위한 좋은 Valgrind 대체품이 있습니까? (0) | 2020.04.30 |
intval과 int-`(int) X`로 캐스팅하는 데 특별한 차이점이 있습니까? (0) | 2020.04.30 |