Функции возвращают неизменные значения. Это так, как это происходит в Swift. Если вы хотите, чтобы он был изменяемым, вы должны сначала сохранить его в var
.
Однако вы можете использовать +
для объединения Array
с любым Sequence
. Так что если filteredApps
является Array
, это должно работать:
let filteredDataOpt: [TimeSeriesEntry?] = filteredApps
.map { data in
let isInDate = dates.contains { date in
guard let d = date else {
return false
}
return Calendar.current.isDate(d, equalTo: data.date, toGranularity: Calendar.Component.day)
}
return isInDate ? self.timeSeriesData(appData: data) : nil
} + self.locationsData.map { data in
let isInDate = dates.contains { date in
guard let d = date else {
return false
}
return Calendar.current.isDate(d, equalTo: data.date, toGranularity: Calendar.Component.day)
}
return isInDate ? self.timeSeriesData(locationData: data) : nil
}
let filteredData = filteredDataOpt.compactMap { $0 }
Есть несколько других вещей, которые мы можем сделать, чтобы очистить этот код. Мы можем вычеркнуть дату теста:
func isValid(_ candidate: Date) -> Bool {
return dates.contains { date in
guard let d = date else {
return false
}
return Calendar.current.isDate(d, equalTo: candidate, toGranularity: Calendar.Component.day)
}
}
let filteredDataOpt: [TimeSeriesEntry?] = filteredApps
.map { data in
return isValid(data.date) ? self.timeSeriesData(appData: data) : nil
} + self.locationsData.map { data in
return isValid(data.date) ? self.timeSeriesData(locationData: data) : nil
}
let filteredData = filteredDataOpt.compactMap { $0 }
В зависимости от ваших данных, может быть лучше предварительно рассчитать действительные Date
диапазоны:
let calendar = Calendar.current
let dayRanges: [Range<Date>] = dates.lazy.compactMap({ $0 }).map({ date in
let start = calendar.startOfDay(for: date)
let end = calendar.date(byAdding: .day, value: 1, to: start)!
return start ..< end
})
func isValid(_ candidate: Date) -> Bool {
return dayRanges.contains(where: { $0.contains(candidate) })
}
Мы могли бы также отделить фильтрацию от преобразования. Это позволяет нам исключить использование compactMap
:
let filteredData = Array(filteredApps.lazy.filter({ isValid($0.date) }).map(self.timeSeriesData))
+ locationsData.lazy.filter({ isValid($0.date) }).map(self.timeSeriesData)
Или мы можем использовать compactMap
дважды:
let filteredData = filteredApps.compactMap({ isValid($0.date) ? self.timeSeriesData(appData: $0) : nil })
+ locationsData.compactMap({ isValid($0.date) ? self.timeSeriesData(locationData: $0) : nil })