快速解析 JSON 数组,对其进行排序并找到重叠的日期

Posted

技术标签:

【中文标题】快速解析 JSON 数组,对其进行排序并找到重叠的日期【英文标题】:parse JSON array in swift , sort it and find overlapping dates 【发布时间】:2022-01-06 20:27:44 【问题描述】:

我该如何解析这个?数组未命名,对象未命名?我还需要对其进行排序并找到事件之间的重叠(识别冲突)如果你们也有任何建议,这对我来说将是一个巨大的帮助。

["title": "Evening Picnic", "start": "November 10, 2018 6:00 PM", "end": "November 10, 2018 7:00 PM", "title": "Nap Break", "start": "November 8, 2018 12:56 PM", "end": "November 8, 2018 1:30 PM", "title": "Football Game", "start": "November 3, 2018 6:14 PM", "end": "November 3, 2018 9:44 PM", "title": "Evening Cookout with Friends", "start": "November 6, 2018 5:00 PM", "end": "November 6, 2018 10:00 PM", "title": "Roller Derby", "start": "November 7, 2018 12:00 PM", "end": "November 7, 2018 2:30 PM", "title": "Basketball Game", "start": "November 8, 2018 7:30 PM", "end": "November 8, 2018 10:30 PM", "title": "Local Pub with Friends", "start": "November 1, 2018 7:33 PM", "end": "November 1, 2018 11:00 PM", "title": "Dentist Appointment", "start": "November 10, 2018 1:45 PM", "end": "November 10, 2018 2:30 PM", "title": "Volleyball With Friends", "start": "November 6, 2018 12:00 PM", "end": "November 6, 2018 1:26 PM", "title": "Free Donuts", "start": "November 9, 2018 3:00 PM", "end": "November 9, 2018 4:00 PM", "title": "TV Show Marathon", "start": "November 9, 2018 4:30 PM", "end": "November 9, 2018 9:00 PM", "title": "Boba Tea Grand Opening", "start": "November 6, 2018 1:27 PM", "end": "November 6, 2018 2:00 PM", "title": "Lunch with Friends", "start": "November 8, 2018 11:30 AM", "end": "November 8, 2018 12:59 PM", "title": "SF Coffee Festival","start": "November 6, 2018 6:00 PM","end": "November 6, 2018 9:00 PM", "title": "Beer with Friends", "start": "November 9, 2018 8:00 PM", "end": "November 9, 2018 9:30 PM", "title": "Yoga", "start": "November 1, 2018 6:00 PM", "end": "November 1, 2018 7:33 PM", "title": "Rock Concert", "start": "November 7, 2018 6:30 PM", "end": "November 7, 2018 11:00 PM", "title": "Lunch Meeting", "start": "November 9, 2018 12:30 PM", "end": "November 9, 2018 2:30 PM", "title": "Bicycling with Friends", "start": "November 1, 2018 6:00 AM", "end": "November 1, 2018 9:30 AM", "title": "Birthday Party", "start": "November 10, 2018 12:30 PM", "end": "November 10, 2018 8:30 PM", "title": "Football Tailgate with John", "start": "November 3, 2018 6:14 PM", "end": "November 3, 2018 9:44 PM"]   

我是 swift 新手,我想知道如何处理这个问题

【问题讨论】:

我要做的第一件事是创建一个Codable 结构,这样您就可以将您的 JSON 放入此类结构的数组中。您可能想要编写自定义解码代码来将日期字符串解析为Dates(请注意,在 JSON 中包含这样的字符串并不是很好 - 这些日期在哪个时区?)。获得结构数组后,您可以按开始日期对其进行排序,然后对其进行迭代以查找重叠;如果后续事件在当前事件结束之前开始,那么您就有重叠。将字符串解析为Dates 的原因是它使比较变得微不足道 【参考方案1】:

考虑到这是您之前的@​​987654321@ 的后续问题。您可以使用 Swift DateInterval 初始化程序创建带有 startend 日期的 DateInverval,并检查它们是否相互交叉:

extension Event 
    var interval: DateInterval  .init(start: start, end: end) 
    func intersects(with event: Event) -> Bool  interval.intersects(event.interval) 


要检查冲突事件,您需要使您的事件符合 Equatable 并过滤与它们相交但不是同一事件的事件:

struct Event: Codable, Equatable 
    let title: String
    let start: Date
    let end: Date


let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .monthDayYearTime
do 
    let events = try decoder.decode([Event].self, from: Data(json.utf8))
    print(events.sorted())
    let conflictingEvents: [(Event, Event)] = events.compactMap 
        for event in events where event != $0 
            if event.intersects(with: $0) && $0.end != event.start && event.end != $0.start  return ($0, event) 
        
        return nil
    
    print(events.count)             // "21\n"
    print(conflictingEvents.count)  // "11\n"
 catch 
    print(error)

【讨论】:

这是最有效的吗?我在想我可能需要通过数组循环来找到它。哪个效率更高? 我不知道您所说的效率是什么意思,这是处理日期间隔的方法。您需要决定要检查哪些事件是否相互重叠。正如我已经说过的,您应该在您的帖子和预期结果中提供一些相互重叠的日期。请查看如何提供minimal reproducible example 我在帖子中将输入更新为完整的 json 数组 @AliAbraham 那么你需要过滤掉那些相互交叉的还是只保留那些相交的? @AliAbraham 请注意,它不是一个代码编写服务,您需要尽最大努力解决您的问题【参考方案2】:

您的 JSON 结构只有两个“困难”的地方,这可能会使它在工作中遇到麻烦。

事实上它是一个直接的 JSON 数组和非标准的日期格式。

我建议从一个好的教程开始,例如 Ultimate Guide to JSON Parsing with Swift,它可能是事实上的来源,因为它几乎涵盖了我迄今为止必须使用的所有用例。

首先定义一个构造来保存基本数据并符合Codable 协议

struct Event: Codable 
    let title: String
    let end: Date
    let start: Date

创建JSONDecoder 并为其提供自定义dateDecodingStrategy

let formatter = DateFormatter()
formatter.dateFormat = "MMMM dd, yyyy hh:mm a"

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(formatter)

您需要将 JSON 响应转换为 Data。我可能已经是这种格式,或者您可以直接转换 String 文本,这是我为测试所做的

let formatter = DateFormatter()
formatter.dateFormat = "MMMM dd, yyyy hh:mm a"
formatter.locale = Locale(identifier: "en_US_POSIX")

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(formatter)

最后,解码响应...

let events = try decoder.decode([Event].self, from: data)

您可以从那里开始处理数据。

排序数组和日期比较是一个很容易被问到的问题,只是有很多例子可供选择,我不打算在这里重复。做一些研究,尝试一些想法。如果您仍有问题,作为另一个(重点)问题并提供您的尝试

【讨论】:

hh:mm 错了,应该是h:mm a。这同样适用于这一天。您还应该将 DateFormatter 的区域设置设置为 "en_US_POSIX" 以避免它反映用户的设备区域设置和 12 小时/24 小时时间设置等设置 @LeoDabus 因为我们将String 传回Date,我不确定hh:mm ah:mm a 会产生什么不同,它会去另一个方式,但我正在对冲我的赌注(我确实测试了代码)。是的en_US_POSIX 是的 DateFormatter 有点宽容,但我避免给它失败的机会:) @LeoDabus 这是我谨慎行事的一种方式-但是,由于它只是指南/示例,因此希望OP可以根据需要对其进行修改;) 你能看看这个帖子***.com/questions/60154926/…

以上是关于快速解析 JSON 数组,对其进行排序并找到重叠的日期的主要内容,如果未能解决你的问题,请参考以下文章

快速解析双 JSON 编码数组并访问它

通俗易懂-动态图解析插入排序快速排序

按属性对 JSON 数组进行排序的通用方法

快速排序与二分查找

仅按第二行对 np 二维数组进行排序[重复]

将图像数组转换为 JSON 文件并在 C# 之后对其进行解码