【问题标题】:Swift: How to create an array of date arrays [ [Date] ], after comparing/splitting two date arrays [Date]Swift:如何在比较/拆分两个日期数组 [Date] 之后创建日期数组 [[Date]] 的数组
【发布时间】:2019-05-06 03:10:09
【问题描述】:

简介

我正在创建一个日历应用程序,我需要管理一个日期数组以便为 UITableView 提供数据。

上下文

数据模型的类型为[Date : [CalendarEvent]],其中CalendarEventNSManagedObject 子类,我将其分类到按事件关联日期属性分组的字典中。我在UITableView 中为该字典的每个键都有一个部分(我不会一次获取所有日历事件)。但是我想添加更多部分来显示事件日期之间的日期间隔间隔,使用类型为[[Date]]的数组

  • 澄清:我的日历应用程序存储了 2 个事件。一场活动 2018-12-05 和一场活动 2018-12-09,今天的日期是 2018-12-01。在这种情况下,我想检索如下数组:[ [2018-12-01, 2018-12-02, 2018-12-03, 2018-12-04], [2018-12-05], [2018-12-06, 2018-12-07, 2018-12-08], [2018-12-09], [2018-12-10] ] 其中每个日期的类型当然都是Date。 (这将产生 4 个部分)

问题

  • 如何对数组进行排序/拆分以满足[[Date]] 格式(在上面的“说明”中进行了解释)?
    • 如果有更简单的方法可以达到相同的结果,那也算是一个答案。

我的尝试

我已经缩小到只显示必要的部分。

class CalendarViewController: UIViewController {
    private let currentCalenar = Calendar.current
    var events : [Date: [CalendarEvent]]? // Events is fetched from todays date and 10 days forward.
    var sectionDates : [[Date]]?

    func getDatesWithEvents() -> [Date]? {
        if let keyArray = events?.keys {
            var dateArray = Array(keyArray)
            dateArray.sort { $0 < $1 }
            return dateArray
        }
        return nil
    }

    func getSectionDatesArray() -> [[Date]]? { 
        var sectionDatesArray : [[Date]] = []
        var currentDate = currentCalendar.startOfDay(for: Date())
        guard let endDate = currentCalendar.date(byAdding: .day, value: 9, to: currentDate), let datesWithEvent = getDatesWithEvents() else { return nil }
        while currentDate < endDate {
            if datesWithEvent.contains(currentDate) {
                sectionDatesArray.append([currentDate])
                sectionDatesArray.append([])
            } else {
                if !sectionDatesArray.isEmpty {
                    sectionDatesArray[sectionDatesArray.count - 1].append(currentDate)
                } else {
                    sectionDatesArray.append([currentDate])
                }
            }
            currentDate = currentCalendar.date(byAdding: .day, value: 1, to: currentDate)!
        }
        sectionDatesArray.removeAll { (sequence) -> Bool in
            sequence.isEmpty
        }
        return sectionDatesArray
   }

感谢您阅读我的问题。

【问题讨论】:

  • 不是'你的两个分支完全一样吗?为什么不使用空数组而不是可选的dateSections?然后你可以使用dateSections.append,甚至map
  • @Sulthan 感谢您的评论!这是一个有效的观点,因为dateSection 永远不会为零。是的,我只是注意到我把它复制错了。尴尬,我会用它来编辑我的问题,但是我的实际尝试并没有更好。然而,问题是我无法弄清楚如何正确地对算法进行语法分析,我显然还不足以成为一个使用 swift 语法的朋友。您介意在答案中展示一个快速示例,说明我如何制定 map 方法吗?下面的当前答案尝试留下了一些问题。
  • 请添加正确的代码。如果您的代码正常工作,codereview.stackexchange.com 可能是一个更好的地方。
  • @Sulthan 看来我在手机上写了上面的评论有点仓促......我已经用我当前的代码更新了我的问题。是的,它暂时有效,但是 Nivs 的回答让我相信这是执行该算法的一种不好的方法,因此我想学习如何有效地/在良好的实践中做到这一点。如果我可以咨询您:这是保持问题公开的正当理由吗?还是我应该使用代码审查姐妹网站?

标签: ios arrays swift sorting date


【解决方案1】:

一般来说,在单个 UITableView 上使用多个数据源会带来运气不佳。..您可能会考虑更改数据模型。

在您的示例中,我会考虑合并这两个数据源,使没有事件的日期值为nil,因此您将其声明为var dates: [Date: [CalendarEvent]?]?

另一种方法——你可以切断这个字典并使用一个数组来存储类型(建议名称)CalendarItem的对象——在那里你可以存储项目的Date[CalendarEvent]?

尽管如此,有很多方法可以做到这一点,我不会全部介绍...

如果你想坚持你的模型,这是我制作的一个函数。这可能不是最佳解决方案,并且有一些魔法可以在 4 行中完成 :) 但是你去-

var currentDate = Date()

// just made up dates
let datesWithEvents: [Date] = [
    Calendar.current.date(byAdding: .day, value: 5, to: currentDate)!,
    Calendar.current.date(byAdding: .day, value: 10, to: currentDate)!
]

let endDate = Calendar.current.date(byAdding: .day, value: 15, to: currentDate)!

var dates: [[Date]] = []
while currentDate < endDate{

    if datesWithEvents.contains(currentDate){
        dates.append([currentDate])
        dates.append([])
    }else{

        if !dates.isEmpty{
            dates[dates.count - 1].append(currentDate)
        }else{
            dates.append([currentDate])
        }
    }

    currentDate = Calendar.current.date(byAdding: .day, value: 1, to: currentDate)!
}

/* prints
 [
    [
        2018-12-04 17:57:44 +0000
        2018-12-05 17:57:44 +0000
        2018-12-06 17:57:44 +0000
        2018-12-07 17:57:44 +0000
        2018-12-08 17:57:44 +0000
    ],
        [2018-12-09 17:57:44 +0000],
    [
        2018-12-10 17:57:44 +0000,
        2018-12-11 17:57:44 +0000,
        2018-12-12 17:57:44 +0000,
        2018-12-13 17:57:44 +0000
    ],
        [2018-12-14 17:57:44 +0000],
    [
        2018-12-15 17:57:44 +0000,
        2018-12-16 17:57:44 +0000,
        2018-12-17 17:57:44 +0000,
        2018-12-18 17:57:44 +0000
    ]
 ]
 */

【讨论】:

  • 您好,感谢您的回答!是的,我会看看我是否可以改变它,让数据模型不需要这么多的排序是有意义的。同时然而我已经实现了你的示例代码,它适用于 2 个 datesWithEvents 但是,当我有 3 个或更多带事件的日期时,它偶尔会返回空数组([[with dates],[带日期]、[]、[带日期]]等)。如果dates.append([ ]) 被删除,则不会发生这种情况,但这将删除dates 中的一些非事件关联日期数组。我自己无法解决这个问题,你介意看看吗?
  • 当日期彼此相隔一天时会出现此问题,可以通过将第一个 if 语句替换为 if datesWithEvents.contains(currentDate){ if dates.last! == []{ dates[dates.count - 1] = [currentDate] }else{ dates.append([currentDate]) } dates.append([]) }else 来解决此问题,但它很难看,所以我建议你再找一个方法,因为我没有足够的时间:(
  • 我添加了一个方法来删除数组中的空数组。这似乎使它成立。我仍然对更好的做法/一种干净的方式感兴趣。我会让这个开放一点,如果我没有得到更好的答案,我会接受这个,因为到目前为止它确实可以正常工作。但是您的其他模型建议似乎需要相同数量的排序逻辑?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-08
  • 1970-01-01
相关资源
最近更新 更多