Reduce array to set in Swift
With Swift 5.1, you can use one of the three following examples in order to solve your problem.
#1. Using Array
's map(_:)
method and Set
's init(_:)
initializer
In the simplest case, you can map you initial array to an array of url
s (String
) then create a set from that array. The Playground below code shows how to do it:
struct MyObject { let url: String}let objectArray = [ MyObject(url: "mozilla.org"), MyObject(url: "gnu.org"), MyObject(url: "git-scm.com")]let urlArray = objectArray.map({ $0.url })let urlSet = Set(urlArray)dump(urlSet)// ▿ 3 members// - "git-scm.com"// - "mozilla.org"// - "gnu.org"
#2. Using Array
's reduce(into:_:)
method
struct MyObject { let url: String}let objectArray = [ MyObject(url: "mozilla.org"), MyObject(url: "gnu.org"), MyObject(url: "git-scm.com")]let urlSet = objectArray.reduce(into: Set<String>(), { (urls, object) in urls.insert(object.url)})dump(urlSet)// ▿ 3 members// - "git-scm.com"// - "mozilla.org"// - "gnu.org"
As an alternative, you can use Array
's reduce(_:_:)
method:
struct MyObject { let url: String}let objectArray = [ MyObject(url: "mozilla.org"), MyObject(url: "gnu.org"), MyObject(url: "git-scm.com")]let urlSet = objectArray.reduce(Set<String>(), { (partialSet, object) in var urls = partialSet urls.insert(object.url) return urls})dump(urlSet)// ▿ 3 members// - "git-scm.com"// - "mozilla.org"// - "gnu.org"
#3. Using an Array
extension
If necessary, you can create a mapToSet
method for Array
that takes a transform
closure parameter and returns a Set
. The Playground below code shows how to use it:
extension Array { func mapToSet<T: Hashable>(_ transform: (Element) -> T) -> Set<T> { var result = Set<T>() for item in self { result.insert(transform(item)) } return result }}struct MyObject { let url: String}let objectArray = [ MyObject(url: "mozilla.org"), MyObject(url: "gnu.org"), MyObject(url: "git-scm.com")]let urlSet = objectArray.mapToSet({ $0.url })dump(urlSet)// ▿ 3 members// - "git-scm.com"// - "mozilla.org"// - "gnu.org"
reduce()
method expects a closure that returns a combined value, while insert()
methods of Set
value does not return anything but instead it inserts a new element into the existing set.
In order to make it work you would need to do something like:
objects.reduce(Set<String>()) { $0.union(CollectionOfOne($1.URL))}
But the above is a bit of an unnecessary complication. If you have a big array, that would mean quite a number of ever-growing sets to be created while Swift goes over all the elements from objects
. Better follow the advice from @NRitH and use map()
as that would make a resulting set in one go.