如何在星期几之前对数据进行分组和汇总?

时间:2015-03-06 10:47:47

标签: ios swift

我有两个数组, nsDates ,其中包含日期,,其中包含值(Int),我想根据星期几对值进行求和。

我在SQL上找到了几个答案,但在swift / objective-c中没有。我在下面写的代码可以解决问题。但它缓慢而冗长。根据星期几对值进行分组和求和的计算效率最高的方法是什么?任何帮助将不胜感激!

我创建了一个函数来获取星期几(即星期日= 1等)

func getDayOfWeek(somedate:NSDate)->Int? {

    let calendar:NSCalendar = NSCalendar.currentCalendar()
    let dateComps:NSDateComponents = calendar.components(.CalendarUnitWeekday , fromDate: somedate)
    let dayOfWeek:Int = dateComps.weekday
    return dayOfWeek
}

我初始化将保存我将要传递的值的数组。

var friday = [Int]()
var saturday = [Int]()
var sunday = [Int]()
var monday = [Int]()
var tuesday = [Int]()
var wednesday = [Int]()
var thursday = [Int]()

我将nsDates中的日期传递给func getDayOfWeek,以获取星期几,如果它是1,那么我将值数组中的相应值附加到我上面初始化的星期日数组中,如果dayOfWeek == 2我把它附加到星期一阵列等。

func appendValuesPerDayOfWeek(){
    for i in 1...nsDates.count{
      var dayOfWeek = getDayOfWeek(nsDates[i-1])
            if dayOfWeek == 1{
                sunday.append(values[i-1])}
            if dayOfWeek == 2{
                monday.append(values[i-1])}
            if dayOfWeek == 3{
                tuesday.append(values[i-1])}
            if dayOfWeek == 4{
                wednesday.append(values[i-1])}
            if dayOfWeek == 5{
                thursday.append(values[i-1])}
            if dayOfWeek == 6{
                friday.append(values[i-1])}
            if dayOfWeek == 7{
                saturday.append(values[i-1])}
        }
}

我执行功能

appendValuesPerDayOfWeek()

为了得到一周中每一天的值的总和,我最后总结了每个数组的元素。

let sumMonday = monday.reduce(0,+)
let sumTuesday = tuesday.reduce(0,+)
let sumWednesday = wednesday.reduce(0,+)
let sumThursday = thursday.reduce(0,+)
let sumFriday = friday.reduce(0,+)
let sumSaturday = saturday.reduce(0,+)
let sumSunday = sunday.reduce(0,+)

3 个答案:

答案 0 :(得分:2)

不是每周都有单独的变量,而是使用一个将星期几映射到值的字典,你可能会更好。

鉴于此更改,您可以编写一个函数groupedReduce,该函数同时使用组合函数和分组函数,并返回组合每个组的字典:

func groupedReduce
  <S: SequenceType, K: Hashable, U>
  (source: S, initial: U, 
   combine: (U, S.Generator.Element) -> U, 
   groupBy: (S.Generator.Element) -> K) 
  -> [K:U] 
{

    var result: [K:U] = [:]

    for element in source {
        let key = groupBy(element)
        result[key] = combine(result[key] ?? initial, element)
    }

    return result
}

let a = [1,5,2,3,7]
let isEven = { $0 % 2 == 0 }
groupedReduce(a, 0, +, isEven)
// returns dictionary of two groupings, false (odd numbers)
// summing to 16 and true (even numbers) summing to 2

这应该很容易适应于采用按星期几分组的功能,并执行您正在寻找的任何求和逻辑。

注意,他们的关键需要是Hashable。您的getDayOfWeek函数返回Int?并且选项不可清除 - 但它看起来不需要返回可选项。在给定日期的情况下,星期几永远不会是未知的,因此它应该返回Int,并且 可以播放。

答案 1 :(得分:1)

我想你在两个独立的数组中有日期和值,也许最简单的方法是:

let days = [NSDate]() // here your dates
let values = [Int]()  // here your values

typealias DayOfWeek = Int
typealias Value = Int

var result: [DayOfWeek : Value] = [:]
for (dayOfWeek, v) in Zip2(days.map(getDayOfWeek), values) {
    let a = result[dayOfWeek] ?? 0
    result[dayOfWeek] = a + v
}

result[1] // should give the sum for the first day of the week

注意我已根据@Airspeed Velocity

的建议更改了getDayOfWeek() -> Int

答案 2 :(得分:0)

您可以使用2维数组来使事情变得更简洁,例如:

var dateValues = Array<Array<Int>>()
for var i = 0; i < 7; i++ {
    dateValues.append(Array<Int>())
}

然后将appendValuesPerDayOfWeek函数修改为索引而不是范围,并插入到2维数组中,如下所示:

func appendValuesPerDayOfWeek(){
    for var i = 0; i < nsDates.count; i++ {
        var dayOfWeek = getDayOfWeek(nsDates[i])
        dateValues[dayOfWeek].append(values[i])
    }
}

然后为了获得一天的总和,我写了一个看起来像这样的函数:

func getSumForDayOfWeek(dayOfWeek: Int) -> Int {
    let array = dateValues[dayOfWeek]
    let sum = array.reduce(0,+)
    return sum
}

这减少了代码量。对于额外的开发人员点,您可以将这些方法封装到您自己的数据结构中以简化:

import UIKit

class DateValues: NSObject {
    var values = Array<Array<Int>>()

    override init() {
        for var i = 0; i < 7; i++ {
            values.append(Array<Int>())
        }
        super.init()
    }

    func addValue(value: Int, forDate date: NSDate) {
        var dayOfWeek = getDayOfWeek(date)
        values[dayOfWeek].append(value)
    }

    func sumFromDayOfWeek(dayOfWeek: Int) -> Int {
        let array = values[dayOfWeek]
        return array.reduce(0,+)
    }

    func getDayOfWeek(somedate: NSDate) -> Int {
        let calendar:NSCalendar = NSCalendar.currentCalendar()
        let dateComps:NSDateComponents = calendar.components(.CalendarUnitWeekday , fromDate: somedate)
        let dayOfWeek:Int = dateComps.weekday
        return dayOfWeek
    }
}

如果你真的想要,你可以使这个泛型也可以处理除Int之外的其他类型,例如Double或String。

我希望这会有所帮助