Currently I've got this chunky reduce function...
blah: [String: Any] = queryItems.reduce([String: Any]()) {
(params: [String: Any], queryItem: URLQueryItem) in
var output = params
output[queryItem.name] = queryItem.value
return output
}
I'm sure there is a much simpler way of doing this but I can't get my head around how that would work.
Is there a "better" way to do this?
By "better" I mean cleaner, shorter, more elegant, etc...
It's possible to use reduce(into:_:) instead of reduce(_:_). This both save you the lines and the overhead of copying params for each iteration:
let blah: [String: Any] = (urlComponents.queryItems ?? []).reduce(into: [:]) {
params, queryItem in
params[queryItem.name] = queryItem.value
}
This method is preferred over
reduce(_:_:)for efficiency when the result is a copy-on-write type, for example an Array or a Dictionary.
You can create a dictionary from the name and value of each query item with
let items = urlComponents.queryItems ?? []
let dict = Dictionary(items.lazy.map { ($0.name, $0.value as Any) },
uniquingKeysWith: { $1 })
In the case of a duplicate name, the later value wins (this can be controlled with the uniquingKeysWith: parameters).
Or remove the as Any cast to get a dictionary of type [String: String?]:
let items = urlComponents.queryItems ?? []
let dict = Dictionary(items.lazy.map { ($0.name, $0.value ) },
uniquingKeysWith: { $1 })
Alternatively
let items = urlComponents.queryItems ?? []
let dict = Dictionary(items.lazy.map { ($0.name, [$0.value] ) },
uniquingKeysWith: +)
to build a dictionary of type [String : [String?]], holding all values for each name.