我有一个结构如下的对象数组:
{
id: String,
userId: String,
distance: Double,
time: Double
}
在数组中,同一用户 ID 在相同距离内可以有多个条目。例如,数组可能是:
[{id: "1", userId: "1", distance: 100, time 18.7}, {id: "2", userId: "1", distance: 100, time : 18.5},
{id: "3", userId: "2", distance: 100, time: 18.2}, {id: "4", userId: "2", distance: 200, time: 41.0}]
我想对数组进行过滤和排序,以便数组仅包含每个用户特定距离的最快时间。因此,如果我想使用上面的数组查找 100 次,它只会返回:
[{id: "3", userId: "2", distance: 100, time: 18.2}, {id: "2", userId: "1", distance: 100, time: 18.5}]
我知道我可以使用 .filter 将其减少到 100 次,并使用 .sort 来按顺序获取时间,但我不知道如何限制每个 userId 1 个条目
虽然像
sort
、filter
和 map
这样的操作很有用并且可以简化代码,但它们都会迭代数组。
使用数组“操作”,您需要:
filter
仅包含所需距离的数组sort
按用户 ID 和时间排列的数组compactMap
仅返回每个用户的第一次(由于排序,您知道每个用户的第一次是最快的)这涉及迭代数组(或其子集)两次并对其进行两次排序。
struct DistanceTime {
let id: String
let userId: String
let distance: Double
let time: Double
}
let times = [DistanceTime(id: "1", userId: "1", distance: 100, time: 18.7), DistanceTime(id: "2", userId: "1", distance: 100, time : 18.5),
DistanceTime(id: "3", userId: "2", distance: 100, time: 18.2), DistanceTime(id: "4", userId: "2", distance: 200, time: 41.0)]
func fastestTimesMap(for distance: Double, from distanceTimes:[DistanceTime]) -> [DistanceTime] {
let filteredTimes = distanceTimes.filter { dt in
return dt.distance == distance
}
let sortedTimes = filteredTimes.sorted { dt1, dt2 in
if dt1.userId != dt2.userId {
return dt1.userId < dt2.userId
} else {
return dt1.time < dt2.time
}
}
var currentUser: String? = nil
let output = sortedTimes.compactMap { dt in
if dt.userId != currentUser {
currentUser = dt.userId
return dt
} else {
return nil
}
}
return output.sorted { dt1, dt2 in
return dt1.time < dt2.time
}
}
let output = fastestTimesMap(for: 100, from: times)
另一种方法是使用
for
循环将数组迭代为:
循环完成后,您仍然需要按
time
对缩减后的数组进行排序,以找到最快的时间:
func fastestTimes(for distance: Double, from distanceTimes:[DistanceTime]) -> [DistanceTime] {
var times=[String:DistanceTime]()
for dt in distanceTimes {
if dt.distance == distance {
if (times[dt.userId] == nil) {
times[dt.userId] = dt
}
if dt.time < times[dt.userId]!.time {
times[dt.userId] = dt
}
}
}
return Array(times.values).sorted { dt1, dt2 in
return dt1.time < dt2.time
}
}
let output = fastestTimes(for: 100, from: times)
不仅代码更少,而且您现在只需遍历一次完整数组并对缩减后的数组进行一次排序。