2010-07-20 8 views
16

Кажется, я часто обрабатываю такие особые случаи. Там должен быть более лаконичный синтаксис или построить:Есть ли способ сделать это?

var x = solveForX(); /* some slow calculation here */ 
if (x < 0) 
{ 
    x = 0; 
} 

Это эквивалентно, но не чувствовать себя более элегантна:

var x; 
x = (x = solveForX()) < 0 ? 0 : x; 

Может быть, есть немного сдвиг трюк?


Update: Я побежал some benchmarks сравнить два моих любимых ответов - тот, который я согласился и Peter Ajtai's. Оказывается, Питер довольно быстро! Выполняя 1 000 000 итераций каждого (я также запускал версию, которая кэширует Math.max, чтобы узнать, сколько времени внес вклад) показывает, что Питер бежит в половине времени версии Math.max, даже с кешированием max.

Тем не менее, даже самый медленный метод все еще довольно быстрый.

+0

Почему бы не обновить solveForX, чтобы вернуть 0, когда это отрицательно? – Fosco

+1

Я верю, он должен работать нормально !! – 2010-07-20 15:21:09

+1

@Fosco - Может быть, его общая функция, и это особый случай –

ответ

29

Как насчет

var x = Math.max(solveForX(), 0); 
+0

Это * * путь. –

+6

FWIW, хотя это более красноречиво, как читатель кода, эта форма занимает меня на несколько секунд дольше, чем синтаксический анализ, чем исходная форма OP –

+3

Не самая ясная вещь, использующая 'Math.max' для реализации минимума. –

10

Что-то вроде:

x = Math.max(0, solveForX()); 
+0

Это * * путь. –

8
(x < 0) && (x = 0); 

Edit: Убрана если заявление. Спасибо Андреасу.

Это одна строка, и ясно, что она делает (по моему личному мнению) - , если вы знакомы с булевой оценкой короткого замыкания.

Выше используется boolean short circuit evaluation. Это может быть очень полезно в определенных ситуациях (особенно для арифметики указателей в C++, но булева оценка короткого замыкания также работает в Javascript).

x = 0 оценивает только, если x < 0.

Вот два примера:

Это предупреждает 1:

<script type="text/javascript"> 
    var x = 1; 
    (x < 0) && (x = 0); 
    alert(x); 
</script> 

Это предупреждает 0:

<script type="text/javascript"> 
    var x = -1; 
    (x < 0) && (x = 0); 
    alert(x); 
</script> 
+0

Видя, что у меня болят глаза! –

+2

x = 0 всегда будет присваивать никогда не оценивать – Woot4Moo

+0

отрицательный ghostrider – Woot4Moo

2

Я украсят оригинальную solveForX функцию.

function returnNonNegative(fn) { 
    function _f() { 
     var x = fn(); 
     if (x < 0) { 
      x = 0; 
     } 
     return x; 
    } 
    return _f; 
} 

solveForX = returnNonNegative(solveForX); 

В данном конкретном случае, используя Math.max, кажется, хорошо, но эта схема обеспечивает общее решение для этого типа задач.

+1

Я думаю, что этот вопрос касается 'x = (x = solveForX()) <0? 0: x; 'сам по себе, а не о функции' solveForX' или контексте OP. –

+0

@Andreas Rejbrand: вопрос был «есть ли более гладкий способ» написания вышеприведенной конструкции, состоящей из вызова функции и некоторого дополнительного поведения. Я думаю, что это типичный случай для декоратора. Синтаксис можно улучшить несколькими способами, но это делает семантику более понятной. –

0

Принятый ответ совершенен.Если вы хотите сделать то же самое без вызова функции, я считаю, что это наиболее кратким:

var x; 
(x = solveForX()) > 0 || (x = 0); 

(В Safari, эта реализация в целом 7% быстрее, чем Math.max(), что, вероятно, не стоит заботиться)

+0

Math.max (за пределами, thunderdome) имеет лучшие сцены боя. – Matt

+0

'var Mad = Math; var x = Mad.max (за пределами, thunderdome); 'FTFY –

0

Я думаю, что этот способ довольно приятный!

var x = Math.max(solveForX(), 0); 

Удачи вам!

+0

Простите, но этот ответ был отправлен несколько раз. Что это добавляет? –

Смежные вопросы