我有2个类型均为[[String:Any]]
的数组,其中每个元素:
["date":Date,"value":CGFloat] //always looks like this
我甚至可能拥有超过2个(!)
我想创建一个具有相同结构的数组,该数组将针对所有出现在每个日期的所有结果(两个或更多)进行求和。
如果array1的日期未出现在其他日期(array2等)上,那么我将对该特定日期简单地将0添加到数组1的值上。
有没有一种简单有效的方法?
答案 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秒或更短的时间是同一日期来检查是否相等。