【问题标题】:A somewhat painful triple-nested ternary operator一个有点痛苦的三重嵌套三元运算符
【发布时间】:2025-12-19 05:05:07
【问题描述】:

我查看了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;
        }
    }
}

我的解释正确吗?我只是问这个,因为如果它不正确,我将面临大量调试。所以。我“明白”了吗?

【问题讨论】:

  • 是的,看起来你的逻辑是对的,除了一些大小写差异
  • if(c == 0) 处的第一个 c 应该是大写 c,不是吗?
  • 嗯,是吗?我感觉就像在飞镖上扔飞镖,我的后腿被绑在背后,蒙上眼睛,打进了一个靶心。是的,@NiftyDude,这是正确的。谢谢你的收获!
  • 看起来正确。由于您正在转换为 python,我相信您不会在意这种情况,但请注意 JavaScript 中的 == 确实类型强制,因此两者可能会有所不同。
  • @dwerner:是的,这是真的。感谢您指出这一点。

标签: javascript if-statement ternary-operator


【解决方案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】:

同样的逻辑可以写成更简单的方式:

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比嵌套ifs要清晰得多。

【讨论】:

  • 非常酷,谢谢。不过,我主要是在寻找逻辑验证,仅供参考。 :)
  • 人们普遍认为,不使用括号所节省的空间/“清洁度”远远超过了对代码可维护性的危险影响。 *.com/a/2125078/205192
【解决方案3】:

是的,没错(除了大小写差异)。然而,它可能写得更简洁,没有任何括号,可读为 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;

【讨论】:

  • 因为我将把它转换成 Python,所以语法并不重要。不过还是谢谢!
  • 我认为 python 的等效项是elif...每个人似乎都希望避免不必要的缩进。
  • @GGG:没错。是的。我想如果你是一名程序员,你的本能就是让任何东西都可读……这不能怪任何人!
  • 人们普遍认为,不使用括号所节省的空间/“清洁度”远远超过了对代码可维护性的危险影响。 *.com/a/2125078/205192
  • @DougW:几乎不会有第二个声明;此代码的唯一目的是分配给单个变量。此外,OP 正在将其转换为 Python,其中实际上没有强制执行括号:-)
【解决方案4】:

根据我个人的喜好,仔细对齐的嵌套三元组胜过 if-else 混乱:

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

【讨论】:

  • 但是在 webkit 中嵌套一元 expr 慢 60%,在 geco 中比 else if 或 switch 慢一点。
  • @Zydnar,我不知道,伙计。我刚刚在 Chrome 控制台中运行了一个简单的基准测试,并且 if-then-else 速度较慢:i.imgur.com/Fqjyifl.png。无论使用哪种变体,单个操作大约需要 0.000000001 秒。那是一纳秒,所以你在这里为皮秒的差异而战!如果您在程序上实时生成数据,那么它可能很重要。但是,对于绝大多数 JS 开发人员来说,这种差异绝对可以忽略不计。重要的是代码可读性和开发速度。
  • 请注意,单次迭代的纳秒包括花费在for 逻辑和= 分配上的时间。
  • 这取决于项目,如果它是一个简单的网站,你不在乎它是否是具有大数据的高性能项目......除了 eslint 还会将嵌套 Tenary 标记为不好的做法,除非你会把它关掉。由于许多原因,即使是后台的某些程序或插件也会影响简单的基准测试。
  • jsben.ch/9zcXt 好的,我的错误 if-else 比较慢,但是 switch 比 unary 和 if-else 快
【解决方案5】:
H = C == 0 
    ? null 
    : V == r 
        ? (g - b) / C 
        : V == g 
            ? (b - r) / C + 2 
            : (r - g) / C + 4

我见过 Dan Abramov 使用这种缩进放置模式。虽然我不喜欢条件运算符? 不再在视觉上遵循条件,但我更喜欢这种方式而不是@lolmaus 的示例,因为无论条件的大小如何,缩进总是一致的。

您实际上开始将其视为? true : false,这在视觉上很直观。通过这种方式,我发现三元组更容易发现并与周围的代码区分开来。

【讨论】:

    【解决方案6】:

    如果您的 JavaScript 代码库包含类似问题的嵌套三元语句,请考虑将格式转换为 daisy chained ternary statements

    H = (C == 0)           // Is C zero?
        ? null             // Then return `null`, else ...
        : (V == r)         // Is V equal to r?
        ? (g - b) / C      // Then return this value, else ...
        : (V == g)         // Is V equal to g?
        ? (b - r) / C + 2  // Then return this value
        : (r - g) / C + 4; // Otherwise fall back to this default value
    

    他们只是在一条直线上从上到下读取,返回一个值 一旦他们遇到了一个真实的条件或后备。

    Nested Ternaries are Great,埃里克·埃利奥特

    【讨论】:

      【解决方案7】:

      这是另一个更优雅的想法...

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

      只需将其包装在函数中并使用而不是 H...

      【讨论】:

        【解决方案8】:

        MDN Docs中所述:

        function example(…) {
            return condition1 ? value1
                 : condition2 ? value2
                 : condition3 ? value3
                 : value4;
        }
        
        // Equivalent to:
        
        function example(…) {
            if (condition1) { return value1; }
            else if (condition2) { return value2; }
            else if (condition3) { return value3; }
            else { return value4; }
        }
        

        【讨论】:

          【解决方案9】:

          为什么不使用 Python 中的三元运算符?

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

          【讨论】: