Switch statement for greater-than/less-than
Więc chcę użyć instrukcji switch takiej jak Ta:
switch (scrollLeft) {
case (<1000):
//do stuff
break;
case (>1000 && <2000):
//do stuff
break;
}
Teraz wiem, że jedno z tych stwierdzeń (<1000
) lub (>1000 && <2000
) nie zadziała (oczywiście z różnych powodów). To, o co proszę, to najskuteczniejszy sposób, aby to zrobić. Nienawidzę używać 30 if
Instrukcji, więc wolałbym użyć składni switch. Mogę coś zrobić?
10 answers
Kiedy spojrzałem na rozwiązania w innych odpowiedziach zobaczyłem pewne rzeczy, które Wiem, że są złe dla wydajności. Miałem zamiar umieścić je w komentarzu, ale pomyślałem, że lepiej jest porównać go i podzielić się wynikami. Możesz przetestować go samodzielnie. Poniżej znajdują się moje wyniki (ymmv) znormalizowane po najszybszej operacji w każdej przeglądarce (pomnóż czas 1.0 z znormalizowaną wartością, aby uzyskać czas bezwzględny w ms).
Chrome Firefox Opera MSIE Safari Node ------------------------------------------------------------------- 1.0 time 37ms 73ms 68ms 184ms 73ms 21ms if-immediate 1.0 1.0 1.0 2.6 1.0 1.0 if-indirect 1.2 1.8 3.3 3.8 2.6 1.0 switch-immediate 2.0 1.1 2.0 1.0 2.8 1.3 switch-range 38.1 10.6 2.6 7.3 20.9 10.4 switch-range2 31.9 8.3 2.0 4.5 9.5 6.9 switch-indirect-array 35.2 9.6 4.2 5.5 10.7 8.6 array-linear-switch 3.6 4.1 4.5 10.0 4.7 2.7 array-binary-switch 7.8 6.7 9.5 16.0 15.0 4.9
Test gdzie wykonywane na Windows 7 32bit z following versions: Chrome 21.0.1180.89 m, Firefox 15.0, Opera 12.02, MSIE 9.0.8112, Safari 5.1.7 . Node został uruchomiony na 64-bitowym Linuksie, ponieważ rozdzielczość timera na węźle.js Dla Windows był 10ms zamiast 1ms.
If-immediate
Jest to najszybsze we wszystkich testowanych środowiskach, z wyjątkiem ... MSIE! (niespodzianka, niespodzianka). Jest to zalecany sposób realizacji to.
if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else
If-indirect
Jest to wariant switch-indirect-array
, ale zamiast tego z if
-statements i działa znacznie szybciej niż switch-indirect-array
w prawie wszystkich testowanych środowiskach.
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
Switch-immediate
Jest to dość szybkie we wszystkich testowanych środowiskach, a właściwie najszybsze w MSIE. Działa, gdy można wykonać obliczenia, aby uzyskać indeks.
switch (Math.floor(val/1000)) {
case 0: /* do something */ break;
case 1: /* do something */ break;
...
case 29: /* do something */ break;
}
Switch-range
Jest to około 6 do 40 razy wolniejsze niż najszybsze we wszystkich testowanych środowiskach z wyjątkiem dla Opery, gdzie trwa około półtora raza dłużej. Jest powolny, ponieważ silnik musi porównać wartość dwukrotnie dla każdego przypadku. Zaskakujące jest to, że Chrome zajmuje prawie 40 razy więcej czasu w porównaniu z najszybszą operacją w Chrome, podczas gdy MSIE zajmuje tylko 6 razy więcej czasu. Ale rzeczywista różnica czasu była tylko 74ms na korzyść MSIE w 1337ms (!).
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;
}
Switch-range2
Jest to wariant switch-range
, ale z tylko jednym porównaniem na przypadek i dlatego szybciej, ale nadal bardzo wolno, z wyjątkiem Opery. Kolejność instrukcji case jest ważna, ponieważ silnik będzie testował każdy przypadek w kolejności kodu źródłowego ECMAScript262:5 12.11
switch (true) {
case (val < 1000): /* do something */ break;
case (val < 2000): /* do something */ break;
...
case (val < 30000): /* do something */ break;
}
Switch-indirect-array
W tym wariancie zakresy są przechowywane w tablicy. Jest to powolne we wszystkich testowanych środowiskach i bardzo powolne w 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;
}
Array-linear-search
Jest to kombinacja liniowego wyszukiwania wartości w tablicy i przełącznika oświadczenie z stałe wartości. Powodem, dla którego ktoś może chcieć tego użyć, jest to, że wartości są znane dopiero w trybie runtime. Jest powolny w każdym testowanym środowisku i trwa prawie 10 razy dłużej w MSIE.
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;
}
Array-binary-switch
Jest to wariant array-linear-switch
, ale z przeszukiwaniem binarnym.
Niestety jest to wolniejsze niż wyszukiwanie liniowe. Nie wiem, czy to moja implementacja, czy wyszukiwanie liniowe jest bardziej zoptymalizowane. Możliwe, że przestrzeń kluczy jest zbyt mała.
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;
}
Podsumowanie
Jeśli wydajność jest ważna, użyj instrukcji if
-lub switch
z natychmiastowymi wartościami.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-07 05:21:30
Alternatywa:
var scrollleft = 1000;
switch (true)
{
case (scrollleft > 1000):
alert('gt');
break;
case (scrollleft <= 1000):
alert('lt');
break;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-15 13:33:21
switch (Math.floor(scrollLeft/1000)) {
case 0: // (<1000)
//do stuff
break;
case 1: // (>=1000 && <2000)
//do stuff;
break;
}
Działa tylko wtedy, gdy masz regularne kroki...
EDIT: skoro to rozwiązanie ciągle się poprawia, muszę doradzić, że rozwiązanie mofolo jest o wiele lepsze
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-05 11:35:02
Możesz utworzyć własny obiekt z kryteriami i funkcją odpowiadającą kryteriom
var rules = [{ lowerLimit: 0, upperLimit: 1000, action: function1 },
{ lowerLimit: 1000, upperLimit: 2000, action: function2 },
{ lowerLimit: 2000, upperLimit: 3000, action: function3 }];
Zdefiniuj funkcje dla tego, co chcesz zrobić w tych przypadkach (zdefiniuj function 1, function 2 itp.)
I "oceń" Zasady
function applyRules(scrollLeft)
{
for(var i=0; i>rules.length; i++)
{
var oneRule = rules[i];
if(scrollLeft > oneRule.lowerLimit && scrollLeft < oneRule.upperLimit)
{
oneRule.action();
}
}
}
Uwaga
Nienawidzę używać 30 wyrażeń if
Wiele razy, jeśli stwierdzenia są łatwiejsze do odczytania i utrzymania. Polecam powyższe tylko wtedy, gdy masz dużo warunków i możliwość dużo wzrostu w przyszłości.
Aktualizacja
Jak zauważył @Brad w komentarzach, jeśli warunki wzajemnie się wykluczają (tylko jeden z nich może być prawdziwy na raz), sprawdzenie górnej granicy powinno być wystarczające:
if(scrollLeft < oneRule.upperLimit)
pod warunkiem , że warunki są zdefiniowane w porządku rosnącym (najpierw najniższy, 0 to 1000
, a następnie 1000 to 2000
na przykład)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-13 07:55:45
Co dokładnie robisz w //do stuff
?
Możesz zrobić coś takiego:
(scrollLeft < 1000) ? //do stuff
: (scrollLeft > 1000 && scrollLeft < 2000) ? //do stuff
: (scrollLeft > 2000) ? //do stuff
: //etc.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-12 14:47:30
Nieprzetestowane i niepewne, czy to zadziała, ale dlaczego nie zrobić kilka if statements
wcześniej, aby ustawić zmienne dla 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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-12 14:47:56
W moim przypadku (kodowanie kolorami procent, nic krytycznego dla wydajności), szybko napisałem to:
function findColor(progress) {
const thresholds = [30, 60];
const colors = ["#90B451", "#F9A92F", "#90B451"];
return colors.find((col, index) => {
return index >= thresholds.length || progress < thresholds[index];
});
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-28 09:09:21
Jest to inna opcja:
switch (true) {
case (value > 100):
//do stuff
break;
case (value <= 100)&&(value > 75):
//do stuff
break;
case (value < 50):
//do stuff
break;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-19 13:18:34
Aktualizacja zaakceptowanej odpowiedzi (nie mogę jeszcze skomentować). Od 1/12/16 używając demo jsfiddle w chrome, switch-immediate jest najszybszym rozwiązaniem.
Wyniki: Rozdzielczość czasowa: 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
Zakończone
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-12 21:36:57
I hate using 30 if statements
Ostatnio miałem taką samą sytuację, tak to rozwiązałem:
Przed:
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;
}
Po:
var scales = [[4, 1], [6, 2], [9, 3], [12, 4], [18, 5]];
scales.forEach(function(el){if(wind_speed > el[0]) scale = el[1]});
I jeśli ustawisz "1, 2, 3, 4, 5" wtedy może być jeszcze prościej:
var scales = [4, 6, 9, 12, 18];
scales.forEach(function(el){if(wind_speed >= el) scale++});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-17 22:22:08