Swift 初学者漫谈:强大的 ~= 操作符

1 阅读2分钟

在这里插入图片描述

概述

在 Swift 语言包罗万象的众多操作符中,~= 无疑是最扑朔迷离的那一个。它的含义和用法会根据具体场景随遇而安,让秃头小码农们爱不释手、心动不已。

在这里插入图片描述

那么,如何提纲挈领的 get 到它所有的奥义呢?本文的内容将为大家解惑。

在本篇博文中,您将学到如下内容:

  1. 让人捉摸不透的 ~= 操作符
  2. 检查值是否在范围内
  3. 藏匿于 switch 语句中的“幽灵”
  4. 按需定制匹配模式
  5. 在示例代码中的含义

闲言少叙,让我们马上开始 ~= 的奇妙之旅吧! Let‘s go!!!;)


1. 让人捉摸不透的 ~= 操作符

在头发半秃小码农们的撸码生涯中,大家多半会遇到一些与 ~= 相关的使用场景。在下面这个例子中,我们使用 NSFetchRequest 将查询到的所有记录(Record)按照时间划分到了各自的小时(Hour)组里:

func groupRecordsByHour(context: NSManagedObjectContext) -> [Int: [Record]] {
    let fetchRequest: NSFetchRequest<Record> = Record.fetchRequest()
    
    do {
        let records = try context.fetch(fetchRequest)
        
        // 按小时分组逻辑
        let groupedRecords = Dictionary(grouping: records) { record -> Int in
            let totalSeconds = record.time  // 直接获取 Int 类型的秒数
            let hour = (totalSeconds / 3600) % 24  // 计算小时(0~23)
            return hour
        }
        
        // 下面这行代码中的 ~= 是神马意思?
        return groupedRecords.filter { 0...23 ~= $0.key }
        
    } catch {
        print("Error fetching records: \(error)")
        return [:]
    }
}

正如大家所见,代码中使用了 ~= 操作符,乍一看好像高深莫测,它在这里到底是什么意思呢?

2. 检查值是否在范围内

在 Swift 中,~~= 被称为模式匹配运算符(它正好和 ruby 的模式匹配运算符是反过来的,ruby 是 =~~),用于检查某个值是否匹配右侧的模式。

它的行为取决于右侧的表达式类型,最常见的用法是判断值是否属于某个范围、枚举或特定模式。

let number = 15

if 0...10 ~= number {
    print("数字在 0 到 10 之间")
} else if 11...20 ~= number {
    print("数字在 11 到 20 之间")  // 这里会输出
}

在上面的代码中,我们利用 ~= 依次判断了 number 处在哪个数字区间中。

3. 藏匿于 switch 语句中的“幽灵”

其实,在我们最常用的 switch 语句中,大家就已经默默的在抱 ~= 操作符的大腿了:

let value = 42

switch value {
case 0...10:    // 隐式调用 0...10 ~= value
    print("小数字")
case 11...100:   // 隐式调用 11...100 ~= value
    print("中等数字")  // 这里会输出
default:
    print("大数字")
}

4. 按需定制匹配模式

然而,~= 操作符最有价值的用途是根据实际情况去“随机应变”。

比如,我们可以用 ~= 来检查名称是否以特定字符开头:

// 自定义字符串前缀匹配
func ~= (pattern: String, value: String) -> Bool {
    value.hasPrefix(pattern)
}

let name = "Alice"
if "A" ~= name {
    print("名字以 A 开头")  // 输出
}

我们还可以用 ~= 检查点的坐标是否在指定的区间内:

func ~= (pattern: (xRange: ClosedRange<Int>, yRange: ClosedRange<Int>), value: (x: Int, y: Int)) -> Bool {
    pattern.xRange ~= value.x && pattern.yRange ~= value.y
}

let point = (x: 5, y: 10)

if (0...10, 0...10) ~= point {
    print("点在 (0...10, 0...10) 范围内")  // 输出
}

从上面两段代码可以看到,我们分别实现了两个自定义 ~= 方法去满足不同的需求,可谓是得心应手,一针见血。

5. 在示例代码中的含义

现在,大家一定都对 ~= 操作符的含义有了更深的了解。我们再回到文章开头的那段实现,在代码 0...23 ~= $0.key 中:

  • 0...23 是闭区间(包含 0 和 23)。
  • ~= 会检查 $0.key 是否在这个区间内。
  • 等价于:0.key >= 0 && 0.key <= 23。

这样做的意义是过滤 groupedRecords 字典内容,仅保留 0-23 小时中的记录:

// 过滤字典,仅保留 key 在 0...23 的键值对
groupedRecords.filter { 0...23 ~= $0.key }

// 等价于:
groupedRecords.filter { $0.key >= 0 && $0.key <= 23 }

那么,为什么用 ~= 而不是直接比较呢?这是因为使用 ~= 有如下好处:

  1. 语义更清晰:明确表达“匹配某个模式”的意图;
  2. 支持复杂模式:除了范围,还可用于枚举、自定义类型等;
  3. 与 switch-case 语法统一:保持代码风格一致;

~= 运算符的核心作用是判断左侧的值是否符合右侧的模式。在区间匹配场景中,它是 >= 和 <= 的语法糖,但更简洁更直观。

至此,小伙伴们都已完全掌握了 ~= 的奥义,赶快给自己一个大大的赞吧!棒棒哒!💯

总结

在本篇博文中,我们讨论了 Swift 语言中强大而又奥妙无穷的 ~= 操作符,我们随后用一些精彩的小示例向大家展示了 ~= 存在的真谛。

感谢观赏,再会啦!8-)