Несколько болезненный трехпоточный тернарный оператор

Я просмотрел исходный код Raphael.js, чтобы узнать, как он преобразовал значения RGB в HSB. Я узнал, как он это сделал, и я был в процессе преобразования его в Python, когда я столкнулся с этим симпатичным тройным вложенным тернарным оператором:

H = (C == 0 ? null :
    V == r ? (g - b) / C :
    V == g ? (b - r) / C + 2 :
             (r - g) / C + 4
    );

Он бросил меня на цикл, потому что у Python нет такого же тройного оператора, что и Javascript. Я потратил некоторое время на то, чтобы посмотреть на него и, в конце концов, испортил этот несколько более чистый код (используя только if/else):

if (C == 0) {
    H = null;
} else {
    if(V == r) {
        H = (g - b) / C;
    } else {
        if(V == g) {
            H = (b - r) / C + 2;
        } else {
            H = (r - g) / C + 4;
        }
    }
}

Была ли моя интерпретация правильной? Я только спрашиваю об этом, потому что, если это неверно, я столкнулся с большой отладкой. Так. "Я получил"?

Ответы

Ответ 1

Я думаю, вы можете избежать этого, чтобы избежать глубокого гнездования:

var H

if(C == 0){
    H = null;
}
else if(V == r){
    H = (g - b) / C;
}
else if (V == g){
    H = (b - r) / C + 2;
}
else {
    H = (r - g) / C + 4;
}

Ответ 2

По моему личному вкусу тщательно выровненная вложенная тройка бьется в беспорядке if-esle:

const H =
  C == 0 ? null            :
  V == r ? (g - b) / C     :
  V == g ? (b - r) / C + 2 :
           (r - g) / C + 4 ;

Ответ 3

Такую же логику можно записать более простым способом:

var H

if (C == 0)
    H = null;
else if (V == r)
    H = (g - b) / C;
else if (V == g)
    H = (b - r) / C + 2;
else
    H = (r - g) / C + 4;

Можно опустить фигурные скобки, потому что в каждом условии есть одно утверждение. И учитывая, что условия взаимоисключающие, использование else if намного яснее, чем вложение if s.

Ответ 4

H = C == 0 
    ? null 
    : V == r 
        ? (g - b) / C 
        : V == g 
            ? (b - r) / C + 2 
            : (r - g) / C + 4

Я видел, как Дэн Абрамов использовал эту схему размещения отступов. Хотя мне не нравится, как условный оператор ? уже не визуально следует за условием, я предпочитаю это примерно как пример @lolmaus, поскольку отступ всегда будет согласован, независимо от размера условного.

Фактически вы начинаете рассматривать его как ? true : false, который визуально интуитивно понятен здесь. И таким образом, я нахожу, что троянец намного легче определить и отличить от окружающего кода.

Ответ 5

Да, это правильно (кроме различий в капитализации). Тем не менее, он может быть чище написан без каких-либо круглых скобок, читаемых как elseif:

if (C == 0)
    h = null;
else if (V == r)
    h = (g - b) / C;
else if (V == g)
    h = (b - r) / C + 2;
else
    h = (r - g) / C + 4;