如何从 NSManagedObject 数组中的每个日期中选择具有最高值的对象



SO上有许多线程解释了从数组中获取最大值的不同方法(map,max(by:),reduce,filteredArrayUsingPredicate)。我还考虑构建一个用于我的fetchRequestNSPredicate。但是我还没有找到任何能让我知道如何完成我正在尝试做的简单事情的线索。

我有一系列LiftEventNSManagedObjects,在任何给定日期都可以有多个LiftEvent。我想每个日期获取一个对象,并且我希望该对象是每个日期上具有最大 oneRepMax 值的对象。

假设我在具有以下属性的数组中有以下LiftEvent对象:

LiftEvent1.date = "3/1/18"
LiftEvent1.oneRepMax = 200
LiftEvent2.date = "3/2/18"
LiftEvent2.oneRepMax = 210
LiftEvent3.date = "3/2/18"
LiftEvent3.oneRepMax = 220
LiftEvent4.date = "3/3/18"
LiftEvent4.oneRepMax = 205
LiftEvent5.date = "3/3/18"
LiftEvent5.oneRepMax = 225

我想挑选出每个日期权重值最高的一个,这将给我这些:

LiftEvent1.date = "3/1/18"
LiftEvent1.oneRepMax = 200
LiftEvent3.date = "3/2/18"
LiftEvent3.oneRepMax = 220
LiftEvent5.date = "3/3/18"
LiftEvent5.oneRepMax = 225

我获取LiftEvent并按如下方式对它们进行排序:

let liftEvents = dataManager.fetchLiftsEventsOfType(liftEventTypeUuid)
var sortedLiftEvents = liftEvents.sorted(by: { $0.date.compare($1.date) == .orderedAscending })

但是,当然,当我这样做时,我会得到一个具有最高oneRepMax值的单个LiftEvent

var maxLiftEvent = sortedLiftEvents.max { a, b in a.oneRepMax < b.oneRepMax }

如何从每个日期获取单个LiftEvent,每个日期在该日期具有最高的oneRepMax值,并确保如果一个日期有多个具有相同oneRepMax值的日期,我只选择一个?

您可以将字典中的所有事件分组,并获取每个日期的最大值。

由于日期可以具有不同的小时/分钟/秒值,因此您需要按天对每个日期进行唯一处理,这可以通过计算给定日期与 1970 年 1 月 1 日之间的天数来完成。

let groupedEvents = Dictionary(grouping: liftEvents, by: { floor($0.date.timeIntervalSince1970 / 86400) })

这将生成一个 [Double: [LiftEvent]] 字典,键是自 1970 年以来的天数,值是当天的事件。

现在,您已将所有事件按天分组,您可以map该字典以查找感兴趣的事件:

let maxEventsPerDay = groupedEvents.map { $1.max(by: { $0.oneRepMax < $1.oneRepMax }) }

结果将是一个事件数组,这些事件具有每个日期的最大oneRepMax

首先,您需要按天对事件进行分组。您可以使用Array.reduce(into:)来创建类型为[Date:[LiftEvent]]的字典,您可以在其中使用Calendar.current.startOfDay对对应于一天的所有Date对象进行分组。

然后,您可以通过Array.max(by:)轻松找到每天的最大事件。

let dailyLiftEvents = liftEvents.reduce(into: [Date:[LiftEvent]](), { dailyLiftEvents, currentLiftEvent in
dailyLiftEvents[Calendar.current.startOfDay(for: currentLiftEvent.date), default: [LiftEvent]()].append(currentLiftEvent)
})
let dailyMaxLiftEvents = dailyLiftEvents.map({$0.value.max(by: {$0.oneRepMax < $1.oneRepMax})})

最新更新