Swift:检查日期是否与日期数组中的任何一天相同?

时间:2018-05-28 19:42:30

标签: swift

我有一组日期对象 - 帖子。而我正在整理一个月。对于每一天,我想检查数组中的某个日期是否在同一天。到目前为止,我有这个:

var date = month?.startOfMonth()
var end = month?.endOfMonth()
while date! <= end! {
   if posts.reduce(false,{Calendar.current.isDate(date, inSameDayAsDate: post.timeStamp)}) == true {
      ....
   }
   date = Calendar.current.date(byAdding: .day, value: 1, to: date!)

}

我认为这是从假的开始,并且在帖子中的每一天它检查它是否在同一天,如果是,它将结果变为真。但是我认为它在下次遇到假值时也会将其更改为假...

如果帖子中的任何日期与某一天相同而不是最后一天,我想要的是返回true。我怎样才能做到这一点?

3 个答案:

答案 0 :(得分:3)

我现在的代码基本上没问题,但我会用reduce替换contains

if let start = month?.startOfMonth(), let end = month?.endOfMonth() {
    var date = start
    var found = false
    while !found && date <= end {
        if posts.contains { Calendar.current.isDate(date, inSameDayAs: $0.timeStamp) } {
            found = true
        }
        date = Calendar.current.date(byAdding: .day, value: 1, to: date)
    }

    if found {
        // We have a match
    }
}

答案 1 :(得分:1)

[已更新] 正如已经正确提到的那样,您可能更感兴趣的是拥有至少有一个帖子的Set天,例如:

let dayComponents: Set<Calendar.Component> = [.day, .month, .year, .era]
let calendar = Calendar.current

let daysWithPosts = Set(posts.map { post in
        calendar.dateComponents(dayComponents, from: post.date)
    })

然后对于每个date,你可以检查它是否在该集合中(上下文不变,请注意力量展开):

while date! <= end! {
    let currentDayComponents = calendar.dateComponents(dayComponents, from: date)
    let postsFound = daysWithPosts.contains(currentDayComponents)
    // <use postsFound as needed>
    date = Calendar.current.date(byAdding: .day, value: 1, to: date!)
}

原始答案,适用于多个日期:

这应该告诉我们某天是否有帖子:

func areTherePosts(in posts: [Post], fromSameDayAs date: Date) -> Bool {
    let calendar = Calendar.current
    let dayComponents: Set<Calendar.Component> = [.day, .month, .year, .era]
    let specificDateComponents = calendar.dateComponents(dayComponents, from: date)

    return posts.contains { post in
        calendar.dateComponents(dayComponents, from: post.date) == specificDateComponents
    }
}

在您的上下文中使用(再次,未更改):

while date! <= end! {
    let postsFound = areTherePosts(in: posts, fromSameDayAs: date!)
    // <use postsFound as needed>
    date = Calendar.current.date(byAdding: .day, value: 1, to: date!)
}

答案 2 :(得分:1)

  

我基本上构建了一个堆栈视图 - 每天 - 我创建一个矩形,如果当天有帖子则为蓝色,如果没有则清除。因此,我可能需要知道这一天。但是,过滤数组中指定月份的元素似乎很有趣。你能说明怎么做吗?也许我可以指定那些日子的位置,然后使用insertItem atIndex

填充其余的stackArray值

基本上,我可以从两个函数开始,一个用于按月过滤日期,另一个按日过滤。我会这样做的原因,在你的情况下,你是每天,你不想重新过滤本月的所有可用日期(但那只是我)

func dates(_ dates: [Date], withinMonth month: Int) -> [Date] {
    let calendar = Calendar.current
    let components: Set<Calendar.Component> = [.month]
    let filtered = dates.filter { (date) -> Bool in
        calendar.dateComponents(components, from: date).month == month
    }
    return filtered
}

func dates(_ dates: [Date], forDay day: Int) -> [Date] {
    let calendar = Calendar.current
    let components: Set<Calendar.Component> = [.day]
    let filtered = dates.filter { (date) -> Bool in
        calendar.dateComponents(components, from: date).day == day
    }
    return filtered
}

您可以使用contains方法,同时匹配月和日,但同样需要考虑开销。在上面的示例中,您只需检查日期是否包含在按月生成的过滤日期中,这可能更接近您所需的结果

nb 这不像firstcontains那样有效,因为这会迭代整个数组找到每个匹配的元素,但是,它有很好的副作用为您提供更多信息。例如,您可以对生成的过滤器进行排序,并简单地从月末开始迭代到最后,在每个匹配日出现时弹出,作为一个想法

大声思考......

另一种方法可能是按月过滤可用日期,如上所述,然后将结果映射到Set天(即Int),这将允许您迭代在每个月的每一天,使用contains(day)执行简单的检查,看看是否包含该日。

同样,您可以将视图映射到每一天并迭代Set,从而更改每个视图的状态。

这一切都取决于更多的上下文然后可用,但不用说,有很多方法可以解决这个问题