【问题标题】:What's a graceful way of doing an "if none of the above"?做“如果以上都不是”的优雅方式是什么?
【发布时间】:2014-06-20 10:04:10
【问题描述】:

我确定你去过那里。你想说“如果 flib 这样做,如果 flob 这样做,如果 flab 做饮食等等”,其中任何数量都可以是真的,那么最后你想要一个“如果你没有做任何一个”。

例如(下面的例子是用 Swift 编写的,因为我一直在使用它,但我认为大多数语言的情况都是一样的):

let thing = 101
var isInteresting = false
if (thing % 3 == 0) {
    println("\"\(thing)\" is a multiple of three.")
    isInteresting = true
}
if (thing > 100) {
    println("\"\(thing)\" is greater than one hundred.")
    isInteresting = true
}
if (thing > 1000) {
    println("\"\(thing)\" is greater than one thousand.")
    isInteresting = true
}
if !isInteresting {
    println("\"\(thing)\" is boring.")
}

我发现跟踪一个布尔值来告诉我我是否做了任何事情有点笨拙。

我想出的唯一其他方法是:

let thing = 101
let isAMultipleOfThree = (thing % 3 == 0)
let isGreaterThan100 = (thing > 100)
let isGreaterThan1000 = (thing > 1000)

if isAMultipleOfThree {
    println("\"\(thing)\" is a multiple of three.")
}
if isGreaterThan100 {
    println("\"\(thing)\" is greater than one hundred.")
}
if isGreaterThan1000 {
    println("\"\(thing)\" is greater than one thousand.")
}
if !(isAMultipleOfThree  || isGreaterThan100 || isGreaterThan1000 ) {
    println("\"\(thing)\" is boring.")
}

但如果有更糟糕的情况(如果你添加一个新子句,你需要记住在三个地方添加它。

所以我的问题是,有没有一种简洁明了的方法?

我梦想着一个虚构的类似 switch 的语句:

switchif {   //Would have fallthrough where every case condition is checked
case thing % 3 == 0:
    println("\"\(thing)\" is a multiple of three.")
case thing >100 :
    println("\"\(thing)\" is greater than one hundred.")
case thing > 1000:
    println("\"\(thing)\" is greater than one thousand.")
none:   //Unlike 'default' this would only occur if none of the above did
    println("\"\(thing)\" is boring.")
}

【问题讨论】:

  • 您需要了解else关键字。
  • 我认为没有比你所做的更好的选择。
  • 继续,Piokuc,演示“else”语句将如何提供帮助。

标签: if-statement switch-statement boolean-logic


【解决方案1】:

这是一个没有完美答案的好问题。但是,除了您建议的想法之外,还有另一个想法:将测试机制封装在一个过程中,以使调用代码至少更加精简。

具体来说,对于你的例子,调用代码可以是这样的:

if (! doInterestingStuff(101)) {
  println("\"\(thing)\" is boring.");
}

如果测试被封装到一个过程中:

  public boolean doInterestingStuff(int thing) {
    var isInteresting = false

    if (thing % 3 == 0) {
      println("\"\(thing)\" is a multiple of three.")
      isInteresting = true
    }
    if (thing > 100) {
      println("\"\(thing)\" is greater than one hundred.")
      isInteresting = true
    }
    if (thing > 1000) {
      println("\"\(thing)\" is greater than one thousand.")
      isInteresting = true
    }

    return isInteresting
  }

【讨论】:

  • 是的,在我看来这更简洁一些,谢谢。
【解决方案2】:

我不确定你在 Swift 中是如何做到这一点的,但由于你没有给出语言标签,我会用 C++ 来回答。

这里的关键是&&是短路的,当第一部分为假时,第二部分不会被评估。它与布尔标志的想法相同,但自动化程度更高。

struct Tracker
{
    Tracker() : any(false) { }
    bool operator()() { any = true; return true; }
    bool any;
};

int thing = 101;
Tracker tracker;
if (thing % 3 == 0 && tracker()) {
    printf("\"%d\" is a multiple of three.\n", thing);
}
if (thing > 100 && tracker()) {
    printf("\"%d\" is greater than one hundred.\n", thing);
}
if (thing > 1000 && tracker()) {
    printf("\"%d\" is greater than one thousand.\n", thing);
}
if (!tracker.any) {
    printf("\"%d\" is boring.\n", thing);
}

查看实际操作:http://ideone.com/6MQYY2

【讨论】:

  • 哦,看起来不错!你不能只使用布尔值作为跟踪器,使用 && tracker = true 吗?
  • @mazz0 我讨厌像这样滥用= 运算符,并且许多编译器会对此产生警告(这是正确的)。但我认为它会起作用。
【解决方案3】:

kjhughes 的回答给了我一点启发:

也许可以编写一个全局函数,它接受不确定数量的键值对(甚至只是两个元素数组),其中键是比较,值是要运行的语句,如果它是真的。如果没有运行,则返回 false,否则返回 true。

更新: 试过了,太可怕了!

//Function:
func ifNone(ifNoneFunc:()->Void, tests: Bool...)
{
    var oneTestPassed = false
    for test in tests
    {
        oneTestPassed |= test
    }
    if(!oneTestPassed)
    {
        ifNoneFunc()
    }
}


//Example:
let thisThing = 7
ifNone(
    {
        println("\(thisThing) is boring")
    },
    {
        if(thisThing % 10 == 0)
        {
            println("\"\(thisThing)\" is a multiple of 10")
            return true
        }
        else
        {
            return false
        }
    }(),
    {
        if(thisThing % 3 == 0)
        {
            println("\"\(thisThing)\" is a multiple of 3")
            return true
        }
        else
        {
            return false
        }
    }(),
    {
        if(thisThing > 1_000_000)
        {
            println("\"\(thisThing)\" is over a million!!")
            return true
        }
        else
        {
            return false
        }
    }()
)

【讨论】:

  • 刚刚注意到我实际上并没有尝试我所描述的,但或多或​​少是一样的......
猜你喜欢
  • 2021-01-04
  • 1970-01-01
  • 1970-01-01
  • 2014-02-03
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 2014-04-26
  • 1970-01-01
相关资源
最近更新 更多