You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中含空字符串的日期字符串数组排序方案

解决含空日期字符串的自定义对象数组排序问题

嘿,这个场景我碰到过好几次,核心思路其实很清晰:先把.medium格式的日期字符串转成真正的Date类型(毕竟字符串直接排序逻辑会乱,空字符串更是没法直接比),然后专门处理空日期的排序规则就行。

第一步:先搞定日期解析的工具

首先得搞一个靠谱的DateFormatter,专门用来解析你这种"Mar 13, 2018"格式的日期字符串:

let dateFormatter: DateFormatter = {
    let formatter = DateFormatter()
    formatter.dateStyle = .medium
    formatter.locale = Locale(identifier: "en_US_POSIX") // 必须指定英文区域,不然系统是中文的话会解析失败
    return formatter
}()

这里一定要加locale,不然如果用户的系统语言是中文,DateFormatter会试图用中文格式解析英文日期,直接返回nil。

第二步:写排序逻辑,处理所有边界情况

排序的时候要覆盖三种场景:两个都有有效日期、两个都是空、一个有一个空。我直接给你完整的可运行代码,基于你提供的testObj:

// 先补全你的自定义对象定义(假设是这样)
struct testObj {
    let dateProp: String
}

// 你的测试数据
let objA = testObj(dateProp: "Mar 13, 2018")
let objB = testObj(dateProp: "Apr 13, 2018")
let objC = testObj(dateProp: "Apr 12, 2018")
let objD = testObj(dateProp: "")
let arr: [testObj] = [objA, objB, objC, objD]

// 核心排序逻辑
let sortedArr = arr.sorted { obj1, obj2 in
    // 把两个对象的日期字符串转成Date
    let date1 = dateFormatter.date(from: obj1.dateProp)
    let date2 = dateFormatter.date(from: obj2.dateProp)
    
    switch (date1, date2) {
    case (.some(let d1), .some(let d2)):
        // 两个都有有效日期:按升序排(旧日期在前),要降序就改成d1 > d2
        return d1 < d2
    case (.none, .some):
        // 第一个是空日期,第二个有:把空的放在前面,不想的话就返回false
        return true
    case (.some, .none):
        // 第一个有日期,第二个是空:把空的放在后面,不想的话就返回true
        return false
    case (.none, .none):
        // 两个都空:保持原顺序(稳定排序),或者直接返回false也可以
        return false
    }
}

// 验证结果
sortedArr.forEach { print($0.dateProp) }
// 输出:""、"Mar 13, 2018"、"Apr 12, 2018"、"Apr 13, 2018"

灵活调整的小技巧

  • 如果你想把空日期放在最后,只需要修改两个case的返回值:把case (.none, .some):改成false,case (.some, .none):改成true。
  • 日期格式化器尽量复用,别在排序闭包里每次都创建,不然数组大了会影响性能。
  • 如果你的日期格式不是英文的,记得把locale改成对应地区的标识符,比如中文用zh_CN。

内容的提问来源于stack exchange,提问作者user3628240

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:55:56