It was pointed out in the comments under the question, but I'd like to clearly state that there is a method for that very same purpose:
mutating func formUnion<S>(_ other: S) where Element == S.Element, S : Sequence
Usage:
var attendees: Set = ["Alicia", "Bethany", "Diana"]
let visitors = ["Diana", "Marcia", "Nathaniel"]
attendees.formUnion(visitors)
print(attendees)
// Prints "["Diana", "Nathaniel", "Bethany", "Alicia", "Marcia"]"
Source: Apple Developer
There is also an immutable variant which returns a new instance containing the union:
func union<S>(_ other: S) -> Set<Set.Element> where Element == S.Element, S : Sequence
Usage:
let attendees: Set = ["Alicia", "Bethany", "Diana"]
let visitors = ["Marcia", "Nathaniel"]
let attendeesAndVisitors = attendees.union(visitors)
print(attendeesAndVisitors)
// Prints "["Diana", "Nathaniel", "Bethany", "Alicia", "Marcia"]"
Source: Apple Developer
Answer from Arkadii on Stack OverflowIt was pointed out in the comments under the question, but I'd like to clearly state that there is a method for that very same purpose:
mutating func formUnion<S>(_ other: S) where Element == S.Element, S : Sequence
Usage:
var attendees: Set = ["Alicia", "Bethany", "Diana"]
let visitors = ["Diana", "Marcia", "Nathaniel"]
attendees.formUnion(visitors)
print(attendees)
// Prints "["Diana", "Nathaniel", "Bethany", "Alicia", "Marcia"]"
Source: Apple Developer
There is also an immutable variant which returns a new instance containing the union:
func union<S>(_ other: S) -> Set<Set.Element> where Element == S.Element, S : Sequence
Usage:
let attendees: Set = ["Alicia", "Bethany", "Diana"]
let visitors = ["Marcia", "Nathaniel"]
let attendeesAndVisitors = attendees.union(visitors)
print(attendeesAndVisitors)
// Prints "["Diana", "Nathaniel", "Bethany", "Alicia", "Marcia"]"
Source: Apple Developer
Swift Set Union
[Swift Set operations]
a.union(b) - a ∪ b - the result set contains all elements from a and b
union- immutable functionunionInPlace(up to Swift v3) =>formUnion- mutable function
[Mutable vs Immutable]
Read more here
You don't have to reduce an array to get it into a set; just create the set with an array: let objectSet = Set(objects.map { $0.URL }).
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 urls (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"
If you know for sure that the NSArray contains only number objects
then you can convert it to an Swift array of Int (or Double or
NSNumber, depending on your needs) and create a set from that:
let nsArray = NSArray(array: [1,2,3,4,5,6,7,8])
let set = Set(nsArray as! [Int])
If that is not guaranteed, use an optional cast:
if let set = (nsArray as? [Int]).map(Set.init) {
print(set)
} else {
// not an array of numbers
}
Another variant (motivated by @JAL's comments):
let set = Set(nsArray.flatMap { $0 as? Int })
// Swift 4.1 and later:
let set = Set(nsArray.compactMap { $0 as? Int })
This gives a set of all NSArray elements which are convertible
to Int, and silently ignores all other elements.
import Foundation
let nsarr: NSArray = NSArray(array: [1,2,3,4,5])
var set: Set<Int>
guard let arr = nsarr as? Array<Int> else {
exit(-1)
}
set = Set(arr)
print(set.dynamicType)
dump(set)
/*
Set<Int>
▿ 5 members
- [0]: 5
- [1]: 2
- [2]: 3
- [3]: 1
- [4]: 4
*/
with help of free bridging, it should be easy ...