Reputation: 707
I’m struggling with using the new map, flatMap, filter, reduce and zip functions. Consider the following: You have two arrays, A and B, containing different objects. For each object in A, you need to find the corresponding object in B (by their id property), and update some of the properties of the object from B. This could be done the old way, using two for cycles, like so:
private func update(statuses: [JobStatus], forJobs jobs: [JobBookPayload]) {
for jobStatus in statuses {
for job in jobs {
if jobStatus.jobId == job.jobId {
job.status = jobStatus.status!
job.option = jobStatus.option!
}
}
}
}
Can this be done using the new functions, to make the code more "Swifty" and improve readability?
Upvotes: 1
Views: 3135
Reputation: 73186
Replacing for .. in .. { if conditional { ... } }
with for .. in .. where conditional { ... }
You could make a minor re-factoring by introducing a where
clause in the inner for
loop to replace the single if
statement of its body:
private func update(statuses: [JobStatus], forJobs jobs: [JobBookPayload]) {
for jobStatus in statuses {
for job in jobs where jobStatus.jobId == job.jobId {
job.status = jobStatus.status!
job.option = jobStatus.option!
}
}
}
Upvotes: 1
Reputation: 1014
I suppose that since you're using classes, you don't actually want to create a new object from the old one. I believe this could be achieved using map
and first
methods:
@discardableResult
func update(statuses: [JobStatus], forJobs jobs: [JobBookPayload]) -> [JobBookPayload] {
return jobs.map({ (payload) -> JobBookPayload in
if let status = statuses.first(where: { payload.jobId == $0.jobId }) {
payload.status = status.status
payload.option = status.option
}
return payload
})
}
Using @discardableResult
will allow you to use this function and ignore the resulting array - the objects inside the initial array were mutated anyway.
Upvotes: 2
Reputation: 949
The idea in the "new" (functional) way, is to create a new object from the previous one:
private func update(statuses: [JobStatus], for jobs: [JobBookPayload]) -> [JobBookPayload] {
return jobs.reduce([]) { newJobs, job in
return newJobs + statuses.flatMap { status in
return status.jobId == job.jobId ?
//Construct a new object
JobBookPayload(status: status.status, option: status.option) : nil
}
}
}
Assuming there is one status
object corresponding to a job
:
private func update(statuses: [JobStatus], for jobs: [JobBookPayload]) -> [JobBookPayload] {
return jobs.reduce([]) { newJobs, job in
return newJobs + statuses.lazy.filter { $0.jobId == job.jobId }.first.flatMap {
JobBookPayload(status: $0.status, option: $0.option) // Construct the object
}
}
}
Avoiding reduce
:
private func update(statuses: [JobStatus], for jobs: [JobBookPayload]) -> [JobBookPayload] {
return jobs.flatMap { job in
return statuses.flatMap { status in
return status.jobId == job.jobId ?
//Construct a new object
JobBookPayload(status: status.status, option: status.option) : nil
}.last
}
}
Upvotes: 0