swift - 如何根据日期进行过滤,以便每周只有一个元素?

标签 swift nsdate nscalendar

我在措辞上遇到困难,但就这样吧。

我有一个 Datapoint 对象数组,每个对象都有一个 createdAt NSDate 属性。该数组包含过去一周每天大约 10 个 Datapoint 对象。

我想过滤数组,以便一周中的每一天只有一个数据点。

我在想一些类似的事情:

        let today = NSDate()
        var endRange = today.dateByAddingTimeInterval(-7 * 24 * 60 * 60)
        var allThisWeeksPoints = datapoints.filter({ $0.createdAt  >= endRange && $0.createdAt < today })
        let c = NSCalendar.currentCalendar()
        var thisWeeksPoints : [Datapoint] = []
        while !c.isDate(endRange, inSameDayAsDate: today) {
            //take one datapoint, eliminate all the other datapoints in the same day and then increment the endRange date by a day
        }

这是我的数据点对象的代码:

class Datapoint: NSObject {
    let object : PFObject

    let objectId : String
    let userId : String
    let createdAt : NSDate
    let totalPosts : Int
    let followerCount : Int
    let followingCount : Int
    let totalLikes : Int
    let averageLikes : Float
    let totalComments : Int
    let averageComments : Float
}

最佳答案

第一步:

使NSDate 可比较 Found here

public func ==(lhs: NSDate, rhs: NSDate) -> Bool {
    return lhs === rhs || lhs.compare(rhs) == .OrderedSame
}

public func <(lhs: NSDate, rhs: NSDate) -> Bool {
    return lhs.compare(rhs) == .OrderedAscending
}

extension NSDate: Comparable { }
<小时/>

一些一般性评论:

  • 使用输入和输出。
  • 尊重上下 Camel 命名约定

将函数分为两部分,一部分用于以周为单位划分点,另一部分用于应用过滤器。这使得维护变得更容易。

按照评论中的建议使用dateByAddingUnit。这将防止本地化问题。并非每周都是相同的,也并非世界上使用的每个日历都使用相同的周系统。

func weeklyPoints(dataPoints: [DataPoint]) -> [[DataPoint]]? {

    guard let firstPoint = dataPoints.first else { // alternative to an .isEmpty check since we need the first point anyway
        return nil
    }

    guard let gregorian = NSCalendar(identifier:NSCalendarIdentifierGregorian) else {
        return nil
    }

    var weeklies : [[DataPoint]] = [[]]
    var weekStart : NSDate = firstPoint.createdAt // force unwrap allowed because of the guard at the beginning
    var maybeWeekEnd : NSDate? = gregorian.dateByAddingUnit(.WeekOfYear, value: 1, toDate: weekStart, options: [])

    for point in dataPoints {

        guard let weekEnd = maybeWeekEnd else {
            break
        }

        guard point.createdAt >= weekStart && point.createdAt < weekEnd else {
            weekStart = weekEnd
            maybeWeekEnd = gregorian.dateByAddingUnit(.WeekOfYear, value: 1, toDate: weekStart, options: [])
            weeklies.append([])
            continue
        }

        let currentWeekIndex = (weeklies.count - 1)
        weeklies[currentWeekIndex].append(point)

    }

    return weeklies

}
<小时/>

非常简单的过滤功能。

func onePointPerWeek(dataPoints: [DataPoint]) -> [DataPoint]? {

    guard let weeklies = weeklyPoints(dataPoints) else {
        return nil
    }

    var pointPerWeek : [DataPoint] = []

    for week in weeklies {
        guard let point = week.first else { // maybe sort them first if needed
            continue
        }
        pointPerWeek.append(point)
    }
    return pointPerWeek
}

关于swift - 如何根据日期进行过滤,以便每周只有一个元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34229309/

相关文章:

swift - 如何在 Swift 中实例化 AnyGenerator<T>?

ios - NSDateFormatter 崩溃

Swift 转换时间到以前

swift - 使用 NSDate() 快速创建 future 日期

swift 用户界面。如何更改 TextField 的占位符颜色?

java - Swift iOS 不确定应用程序或远程服务器是否应该处理 amazon s3

ios - Swift 2.0 - 二元运算符 "|"不能应用于两个 UIUserNotificationType 操作数

background - 当应用处于后台模式时(iOS 7)在特定时间播放声音

swift - 两个 Date 对象之间的所有日期 (Swift)

objective-c - 如何清除 NSDate 毫秒