ChatGPT解决这个技术问题 Extra ChatGPT

我可以在 Swift 中将范围运算符与 if 语句一起使用吗?

是否可以将范围运算符 .....< 与 if 语句一起使用。可能是这样的:

let statusCode = 204
if statusCode in 200 ..< 299 {
  NSLog("Success")
}

A
Ahmad F

您可以使用“模式匹配”运算符 ~=

if 200 ... 299 ~= statusCode {
    print("success")
}

或者带有表达式模式的 switch 语句(在内部使用模式匹配运算符):

switch statusCode {
case 200 ... 299:
    print("success")
default:
    print("failure")
}

请注意,..< 表示忽略上限值的范围,因此您可能需要 200 ... 299200 ..< 300

附加信息:当上述代码在 Xcode 6.3 中编译并打开优化时,然后进行测试

if 200 ... 299 ~= statusCode

实际上根本没有生成函数调用,只有三个汇编指令:

addq    $-200, %rdi
cmpq    $99, %rdi
ja  LBB0_1

这与生成的汇编代码完全相同

if statusCode >= 200 && statusCode <= 299

你可以用

xcrun -sdk macosx swiftc -O -emit-assembly main.swift

从 Swift 2 开始,这可以写成

if case 200 ... 299 = statusCode {
    print("success")
}

对 if 语句使用新引入的模式匹配。另见Swift 2 - Pattern matching in "if"


酷,这是 O(1) 吗?另外,如果 Swift 有一个 switch 语句的简写形式,例如 Scala,那就太好了。但考虑到你总是被迫在 Swift 编译时处理所有可能性,它可能并不真正可行。
@Sky:从生成的汇编代码中可以看到调用了库函数 func ~= (Range<A>, A) -> Bool。我会假设此函数适用于 O(1)。
@Downvoter:一些解释性评论会很好,这样我就可以改进或修复答案......
@MartinR 你如何知道汇编语言调用了哪个函数。Hopper? +1 很酷的答案
@codester:我在命令行上用 xcrun -sdk macosx swift -emit-assembly main.swift 编译了代码并检查了汇编代码。然后我使用 xcrun swift-demangle ... 来消除被调用函数的名称。 - 不幸的是,Xcode 还不能为 Swift 文件创建汇编代码,也许它会在以后的版本中工作。
S
Serhii Yakovenko

这个版本似乎比模式匹配更具可读性:

if (200 ... 299).contains(statusCode) {
    print("Success")
}

正是我正在寻找的
我收到此错误 => Can't form Range with upperBound < lowerBound
C
Community

这是一个旧线程,但在我看来,我们对此考虑过度了。在我看来,最好的答案就是

if statusCode >= 200 && statusCode <= 299

没有

if 200 > statusCode > 299

我知道的形式,其他建议的解决方案是执行函数调用,这更难阅读,执行起来可能更慢。模式匹配方法是一个有用的技巧,但似乎不适合这个问题。

编辑:

就个人而言,我发现模式匹配运算符很可怕,并希望编译器支持 if x in 1...100 语法。这比 if 1...100 ~= x 更直观、更易于阅读


你说得对,这个版本更好读,我只是试图回答明确的问题“是否可以使用范围运算符...?”但是 Xcode 6.3 beta(在优化模式下)为 if 200 ... 299 ~= statusCode 生成了三个汇编指令,没有函数调用:)
实际上 if 200 ... 299 ~= statusCode 给出了 same 汇编代码作为 if statusCode >= 200 && statusCode <= 299
除非此条件位于每秒访问数千次的关键部分,否则担心函数调用开销是过早的优化。即使这样,我也会更担心函数调用在做什么,而不是调用它的成本。不过,@MartinR 很好地证明了无论如何都没有成本。
@rickster,确实如此。作为习惯,我仍然倾向于更喜欢高效的结构而不是低效的结构(假设可读性相似)。并不是说我在这上面浪费了太多时间,但知道不同方法的成本是多少仍然是值得的。
这是吹毛求疵,但我不同意您的建议,即您的 if 语句比@SerhiiYakovenko 发布的答案更具可读性或可理解性。只需在 DRY 的基础上 - 您两次命名“statusCode”。在我决定应该在此处使用名为“statusValue”而不是“statusCode”的不同变量之后,在深夜睡眼惺忪的调试会话中,我可能会犯错误,即更改其中一个变量名而不是另一个.
a
abhimuralidharan

我想检查除 401 之外的 4xx 错误。这是代码:

let i = 401

if 400..<500 ~= i, i != 401 {
    print("yes")
} else {
    print("NO")
}

m
marc_s

我也更喜欢 Range .contains() 运算符,直到发现它的实现效率低下 - https://oleb.net/blog/2015/09/swift-ranges-and-intervals/

我们可以使用一个范围来表示条件 x < 0: (Int.min..<0).contains(x) 是完全等价的。但是,它要慢得多。 contains(_:) 的默认实现会遍历整个集合,并且在最坏的情况下执行一个循环九 quintillion 次并不便宜。


此信息已过时且错误。你写答案的时候就已经错了。
I
Irsyad Ashari

如果您想知道响应状态码是否成功,只需这样

  if response.statuscode < 300 {
      print("response is a success")
  }

如果您从 200,201,203,204 ... 300 进行迭代。不必要的迭代太多了。希望这可以帮助! :D