How can we create unique object list in Swift language like NSSet
& NSMutableSet
in Objective-C.
Always in such a case the critical factor is how to compare objects and what types of objects go into the Set. Using a Swift Dictionary, where the Set objects are the dictionary keys, could be a problem based on the restrictions on the key type (String, Int, Double, Bool, valueless Enumerations or hashable).
If you can define a hash function on your object type then you can use a Dictionary. If the objects are orderable, then you could define a Tree. If the objects are only comparable with ==
then you'll need to iterate over the set elements to detect a preexisting object.
// When T is only Equatable
class Set<T: Equatable> {
var items = Array<T>()
func hasItem (that: T) {
// No builtin Array method of hasItem...
// because comparison is undefined in builtin Array
for this: T in items {
if (this == that) {
return true
}
}
return false
}
func insert (that: T) {
if (!hasItem (that))
items.append (that)
}
}
The above is an example of building a Swift Set
; the example used objects that are only Equatable
- which, while a common case, doesn't necessarily lead to an efficient Set
implementations (O(N) search complexity - the above is an example).
I've built an extensive Set
type similar to the built-in Array
and Dictionary
- here are blog posts one and two and a GitHub repository:
Swift has no concept of sets. Using NSMutableSet
in Swift might be slower than using a Dictionary
that holds dummy values. You could do this :
var mySet: Dictionary<String, Boolean> = [:]
mySet["something"]= 1
Then just iterate over the keys.
You can use any Objective-C class in Swift:
var set = NSMutableSet()
set.addObject(foo)
As of Swift 1.2 (Xcode 6.3 beta), Swift has a native set type. From the release notes:
A new
Set
data structure is included which provides a generic collection of unique elements, with full value semantics. It bridges withNSSet
, providing functionality analogous toArray
andDictionary
.
Here are some simple usage examples:
// Create set from array literal:
var set = Set([1, 2, 3, 2, 1])
// Add single elements:
set.insert(4)
set.insert(3)
// Add multiple elements:
set.unionInPlace([ 4, 5, 6 ])
// Swift 3: set.formUnion([ 4, 5, 6 ])
// Remove single element:
set.remove(2)
// Remove multiple elements:
set.subtractInPlace([ 6, 7 ])
// Swift 3: set.subtract([ 6, 7 ])
print(set) // [5, 3, 1, 4]
// Test membership:
if set.contains(5) {
print("yes")
}
but there are far more methods available.
Update: Sets are now also documented in the "Collection Types" chapter of the Swift documentation.
You actually can create a Set object pretty easy (in contradiction to GoZoner, there is a built in contains method):
class Set<T : Equatable> {
var items : T[] = []
func add(item : T) {
if !contains(items, {$0 == item}) {
items += item
}
}
}
and you maybe even want to declare a custom operator:
@assignment @infix func += <T : Equatable> (inout set : Set<T>, items : T[]) -> Set<T> {
for item in items {
set.add(item)
}
return set
}