首页 > 解决方案 > 按自定义时间间隔对对象数组进行分组

问题描述

我有一系列帖子,我目前按天分组。我使用以下功能来做到这一点;

private func splitDay(from date: Date) -> Date {
    let calendar = Calendar.current
    let components = calendar.dateComponents([.year, .month, .day], from: date)
    return calendar.date(from: components)!
}

private func sectionPosts(posts: [Post]) {
    let groups = Dictionary(grouping: posts) { (posts) in
        return splitDay(from: Date(timeIntervalSince1970: posts.createdOn))
    }
    self.sections = groups.map { (date, posts) in
        return PostSection(date: date, posts: posts)
    }
}

但是,我想实现一个自定义分组,如下所示;

  1. 今天
  2. 昨天
  3. 本星期
  4. 这个月
  5. 年长者

我将如何将其构建到我的分组功能中?我的部分结构是这样的;

struct PostSection {
    var date: Date
    var posts: [Post]
}

标签: iosswiftmappinggrouping

解决方案


由于您尝试将数据分组为“今天”、“昨天”、“本周”和“本月”等组,因此您应该首先创建一个类型来表示这些组:

enum PostGroup {
    case today
    case yesterday
    case thisWeek
    case thisMonth
    case older
    case coming // added "coming" group so that the groups cover all possible dates
}

然后你的PostSection结构将有一个PostGroup属性,而不是一个Date属性:

struct PostSection {
    let group: PostGroup
    let posts: [Post]
}

现在我们只需要一个(Post) -> PostGroup可以传递给Dictionary(grouping:by:). 这可以通过将发布日期的日期组件与今天的日期组件进行比较来实现:

func group(for post: Post) -> PostGroup {
    let today = Date()
    let calendar = Calendar.current
    let postDateComponents = calendar.dateComponents([.year, .month, .day], from: post.createdOn)
    let todayDateComponents = calendar.dateComponents([.year, .month, .day], from: today)
    if postDateComponents == todayDateComponents {
        return .today
    }
    let daysDifference = calendar.dateComponents([.day], from: postDateComponents, to: todayDateComponents)
    if daysDifference.day == 1 {
        return .yesterday
    }
    let postWeekComponents = calendar.dateComponents([.weekOfYear, .yearForWeekOfYear], from: post.createdOn)
    let todayWeekComponents = calendar.dateComponents([.weekOfYear, .yearForWeekOfYear], from: today)
    if postWeekComponents == todayWeekComponents {
        return .thisWeek
    }
    if postDateComponents.year == todayDateComponents.year &&
        postDateComponents.month == todayDateComponents.month {
        return .thisMonth
    }
    if post.createdOn < today {
        return .older
    } else {
        return .coming
    }
}

要完成它:

private func sectionPosts(posts: [Post]) {
    let groups = Dictionary(grouping: posts, by: group(for:))
    self.sections = groups.map { (group, posts) in
        return PostSection(group: group, posts: posts)
    }
}

推荐阅读