我正在尝试获取各个领域记录的聚合数据,以便将其绘制在图表上。
我有一个“WorkDay”领域对象,其中存储了“开始时间”、“结束时间”、“单一时间收入”、“惩罚性收入”、“总收入”等值。
一个图表示例是,我想收集一整年所有工作日的“总收入”,并将其与前几年所有工作日的“总收入”绘制成图表。
我目前的方法是使用"for循环“循环给定年份的所有WorkDay领域对象,并将WorkDay中的值存储在自定义数据结构中。我将领域WorkDay对象中的值移动到数据结构中的数组中。我之所以要将它们添加到数组中,是因为这样可以计算该年份的”averageTotalIncome“以及”totalIncome“。在数组上运行“reduce(0,+)”,可以为整个一年创建一个数组。
自定义数据结构看起来类似于:
import Foundation
import SwiftDate
struct TimePeriodData {
//MARK: - Time Period
var timePeriod: TimePeriod = .week
var date: Date = Date()
var localDate: Date = Date()
//MARK: - Work Day Times
var startTimeArray: [Date] = []
var endTimeArray: [Date] = []
//MARK: - Work Day Hours
var hoursSingleTimeArray: [Double] = []
var hoursPenaltyArray: [Double] = []
var hoursTotalArray: [Double] = []
//MARK: - Work Day Income
var singleTimeIncomeArray: [Double] = []
var penaltyIncomeArray: [Double] = []
var totalIncomeArray: [Double] = []
}
然后,我从领域收集所有工作日,函数如下所示:
private func updateWorkDays() {
// Get Time Period Dates
let start = timePeriodStart()
let end = timePeriodEnd()
// Get Current User Work Days for Time Period
let allUserWorkDays = realm.objects(WorkDay.self).where { workDay in
workDay.date.contains(start ... end)
}
workDays = allUserWorkDays
}
一旦我有了工作日,我就将数据移动到“TimePeriodData”中,SwiftUI将使用它来生成图表等。代码如下所示:
private func getData(for inputDate: Date, from inputWorkDays: Results<WorkDay>) -> TimePeriodData {
var data = TimePeriodData()
for workDay in inputWorkDays {
// Time Period
data.timePeriod = self.timePeriod
data.date = inputDate
data.localDate = workDayListBrain.getLocalDate(from: inputDate)
// Work Day Times
data.startTimeArray.append(workDay.startTime)
data.endTimeArray.append(workDay.endTime)
// Work Day Hours
data.hoursSingleTimeArray.append(workDay.hoursSingleTime)
data.hoursPenaltyArray.append(workDay.hoursPenalty)
data.hoursTotalArray.append(workDay.hoursTotal)
// Work Day Income
data.singleTimeIncomeArray.append(workDay.singleTimeIncome)
data.penaltyIncomeArray.append(workDay.penaltyIncome)
}
return data
}
当“getData”返回时,UI将更新。但是,我发现当我对一整年使用“getData”时,我需要循环100个工作日对象,这需要大约2秒。我知道我还需要为前几年创建“TimePeriodData”,以便根据其他数据绘制图形。假设他们有100个工作日,每个都需要2秒。这加起来很快。
我看过其他帖子,人们循环50,000个领域对象,只需要0.1秒。考虑到我只循环100个领域对象,只需要2秒,我在这里做了什么根本性的错误吗?有没有更好的方法来处理这个问题?
到目前为止,我尝试使用map函数而不是'for循环',看起来有点像这样:
data.startTimeArray = inputWorkDays.compactMap { workDay in workDay.startTime } as [Date]
data.endTimeArray = inputWorkDays.compactMap { workDay in workDay.endTime } as [Date]
但是“compactMap”在速度上并没有明显的提高。我也试着在BG线程上完成这一切,这让事情“感觉”更快,因为UI在处理数据时从来没有停滞过,但它仍然需要2秒钟来更新。
如果您能提供任何帮助或建议,我们将不胜感激。谢谢!
1条答案
按热度按时间h7wcgrx31#
在Realm论坛上有更详细的答案,但我将在这里包括它的要点。
问题中的代码有一些问题,但最大的罪魁祸首是重复迭代数据-这将导致延迟,但也因为它是在主线程将暂停UI。
基于这个问题,所有需要的点都可以通过单个查询来完成,这些查询不仅速度快,而且不需要迭代。像这样的东西
下面是如何在
getData
函数中而不是在循环中实现这一点:另外两个问题出现了;一个是关于当对象有零值和中值时的平均值。让我在这里解决它们
平均值为零(其中WorkDay对象
driveAway
是可选的然后是中值(如有需要,根据上文合并零处理过滤器)