如何根据日期进行过滤,这样每周只有一个元素?

时间:2015-12-11 17:35:28

标签: 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
        }

以下是我的Datapoint对象的代码:

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
}

2 个答案:

答案 0 :(得分:1)

第一步:

制作NSDate Comparable 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 { }

一些一般性评论:

  • 使用输入和输出。
  • 尊重上下骆驼命名惯例

将功能拆分为两部分,一部分用于将点分为几周,另一部分用于应用滤波器。这使得维护更容易。

根据评论中的建议使用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
}

答案 1 :(得分:0)

所以我找到了一种方法:

func thisWeeksPoints() -> [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) {
            if let point = allThisWeeksPoints.first {
                allThisWeeksPoints = allThisWeeksPoints.filter({!c.isDate(point.createdAt, inSameDayAsDate: $0.createdAt)})
                thisWeeksPoints.append(point)
            }
            endRange = endRange.dateByAddingTimeInterval(24 * 60 * 60)
        }

        return thisWeeksPoints
    }