根据日期合并字典数组

时间:2018-11-25 08:55:12

标签: arrays swift dictionary

我有2个类型均为[[String:Any]]的数组,其中每个元素:

["date":Date,"value":CGFloat] //always looks like this

我甚至可能拥有超过2个(!)

我想创建一个具有相同结构的数组,该数组将针对所有出现在每个日期的所有结果(两个或更多)进行求和。

如果array1的日期未出现在其他日期(array2等)上,那么我将对该特定日期简单地将0添加到数组1的值上。

有没有一种简单有效的方法?

2 个答案:

答案 0 :(得分:1)

代替字典使用结构,更方便:

struct MyStruct {
    let date: Date
    let value: CGFloat
}

让我们创建3个MyStruct数组:

let now = Date()
let later = now.addingTimeInterval(3600)
let earlier = now.addingTimeInterval(-3600)

let array1: [MyStruct] = [MyStruct(date: now, value: 1),
                          MyStruct(date: later, value: 2)]
let array2: [MyStruct] = [MyStruct(date: now, value: 3),
                          MyStruct(date: later, value: 4)]
let array3: [MyStruct] = [ MyStruct(date: earlier, value: 5),
                           MyStruct(date: later, value: 6)]

现在,让我们对元素进行分组,并为具有相同value属性的元素添加date

let allArrays = array1 + array2 + array3
let dict = Dictionary(allArrays.map { ($0.date, $0.value) },
                      uniquingKeysWith: { $0 + $1 })

您现在所要做的就是将其转换回MyStruct的数组:

let newArray = dict.map { MyStruct(date: $0.key, value: $0.value) }

您可以像这样检查结果:

for element in newArray {
    print("date =", element.date, "value =", element.value)
}

答案 1 :(得分:0)

我发现了一种方法,即假设数据位于结构(而非dic)内部,这是一种更好的做法。

我将所有数组放入一个大数组中,按日期排序,在其上循环,只要日期等于先前的日期(或足够接近相等),我就将这些值加起来。当下一个日期不同时,我将保存日期和总和。

       //create a combined array from all given arrays
        var combined = [RootData]()
        for list in dataSets {combined.append(contentsOf: list)}

        //sort it by dates
        let sortedArray =   combined.sorted {  $0.date < $1.date }

        //new array - sum of all
        var sumData = [RootData]()

        var last:Date = sortedArray[0].date //set starting point
        var sum:CGFloat = 0
        for element in sortedArray
        {
            //same date - accumulate(same is less than 1 sec difference)
            if(abs(element.date.seconds(from: last)) <= 1) {
                sum+=element.value
            }
            //save
            else {
                sumData.append(RootData(value:sum,date:last))
                sum=element.value
            }
            last=element.date
        }
   //last object
    sumData.append(RootData(value:sum,date:last))

    return  averageData

此处RootData是具有以下内容的简单数据结构:

value:CGFloat
date:Date

按预期工作。 由于日期并不总是完全相等,因此我通过假设1秒或更短的时间是同一日期来检查是否相等。