Structures

The following structures are available globally.

  • A Multiset is an unordered collection of hashable elements.

    The Multiset collection has similarities with Set and Dictionary, two collections in the swift standard library The key difference from a set is that a Multiset can have repeated Elements. It does this by storing a dictionary (called ‘content’) of type [Element, Int].

    Initialisation

    A Multiset can be created by an array literal of type [Element] as in:

    let ingredients: Multiset = ["coffee", "milk", "sugar", "sugar"]
    

    or using variadic initialiser for two or more elements:

    let fruit = Multiset("Apple", "Orange", "Apple")   // ["Apple":2, "Orange":1]
    // But can't do Multiset("Apple") because "Apple" is seen as an array of Characters!)
    

    or using a dictionary literal of type [Element:Int] as in:

    let truth: Multiset = [true:3, false:2]
    

    or from a sequence (which may include repeated elements):

    let numbers: Multiset = [1000, 2000, 3000, 1000]  // [1000:2, 2000:1, 3000:1]
    

    for an empty multiset you must specify the Generic Parameter:

    let words:  Multiset<String> = []
    let numbers = Multiset<Int>()
    

    Inserting and Removing Elements

    To insert elements:

    var multi = Multiset<String>()    // []
    multi.insert("Small")             // ["Small":1]
    multi.insert("Small")             // ["Small":2]
    multi.insert("Big", count: 6)     // ["Small":2, "Big"]
    

    To remove elements:

    var multi: Multiset = [1000:1, 2000:1, 3000:10]
    multi.remove(1000)                // [2000:1, 3000:10]
    multi.remove(3000, count: 3)      // [2000:1, 3000:7]
    multi.remove(3000, count: 3)      // [2000:1, 3000:7]
    

    If there aren’t enough elements then remove will not remove any of them and this is indicated by the function returning false:

    var multi: Multiset = [2000:1, 3000:7]
    let resulta = multi.remove(7777)      // resulta is false
    let resultb = multi.remove(3000, count: 10)  // resultb is false
    

    Or to remove as many as are available then use the isPossible override:

    var multi: Multiset = [2000:1, 3000:7]
    let resulta = multi.remove(ifPossible: 3000, count: 100)  // resulta is 7 and multi is [2000:1]
    let resultb = multi.remove(ifPossible: 3000:100)  // resultb is false
    

    To remove all of certain elements:

    var multi: Multiset = ["AAA":3, "BBB":4, "CCC":4]
    multi.removeAll("AAA")   // ["BBB":4, "CCC":4]
    multi.removeAll()        // []
    

    To just set the number of a certain type of element:

    var truth: Multiset = [true:3, false:4]
    truth.update(count: 5, for: true)    // [true:5, false:4]
    truth.update(count: 0, for: false)   // [true:5]
    truth.update(count: 7, for: false)   // [true:5, false:7]
    

    Iterating

    There are 3 ways to iterate through a multiset:

    1) To iterate through all the elements of a multiset:

    for size in Multiset(["Big":3, "Small":2]) {
        print(size)
    }
    Note that elements of the same type will come grouped together
    but the order of different groups is not defined so:
    either prints "Big"   "Big"   "Big" "Small" "Small"
    or     prints "Small" "Small" "Big" "Big"   "Big"
    

    2) To iterate through groups of different types of elements use grouped()

    for (element, count) in Multiset(["Big":3, "Small":2]).grouped() {
        print(element, count)
    }
    Note that the order of the elements is not defined so:
    either prints ("Big",3)    and then  ("Small":2)
    or     prints ("Small":2)  and then  ("Big",3)
    

    3) To iterate through just the distinct elements of a multiset use distinct():

    for size in Multiset(["Big":3, "Small":2]).distinct() {
        print(size)
    }
    Note that the order of the elements is not defined so:
    either prints "Big"    and then  "Small"
    or     prints "Small"  and then  "Big"
    

    Sequence and Collection Operations

    In addition to the Multiset type’s multiset operations, you can use any nonmutating sequence or collection methods with a multiset.

    let factorsOf12: Multiset = [2:2, 3:1]
    if factorsOf12.isEmpty {
        print("No factors")
    } else {
        print("Twelve has \(factorsOf12.count) factors.")
        print("Twelve has \(factorsOf12.distinctCount) distinct factors.")
    }
    // Prints "Twelve has 3 factors."
    // Prints "Twelve has 2 distinct factors."
    
    let factorsProduct = factors.reduce(1, *)
    // 'factorsProduct' == 12
    
    let factorsStrings = factors.sorted().map(String.init)
    // 'primeStrings' == ["2", "2", "3"]
    

    And as a collection you can use index operations:

    var multi: Multiset = ["AA":3, "BB":3]
    if let index = multi.firstIndex(of: "BB") {
        multi.remove(at: index)     // ["AA":3, "BB":2]
     }
    

    Set Algebra Operations

    Multiset provides the Set Algebra operations which are the same as the ones used by Set. You can test a multiset for membership of an element or check its intersection with other multisets:

  • contains(_:) tests whether a multiset contains a specific element.
  • equal to operator (==) tests whether two multisets contain the same elements and the sanem number of those elements.
  • isSubset(of:) tests whether another multiset contains at least as many of each of the current multisets elements.
  • isSuperset(of:) tests whether a multiset contains at least as many of each of another multisets elements.
  • isStrictSubset(of:) and isStrictSuperset(of:) test whether a multiset is a subset or superset of, but not equal to, another multiset.
  • isDisjoint(with:) tests whether a multiset has any elements in common with another multiset.

  • Note

    Note that when multisets have more than one of the same element some of these operations may not be as obvious as with sets. For example even though: AAB = Multiset([A:2, B:1]) and ABB = Multiset([A:2, B:1]) both contains A and B and no other elements, neither contains the other.

    You can also combine, exclude, or subtract the elements of two multisets:

  • union(_:) creates a new multiset with the elements of a multiset and another multiset or sequence.
  • intersection(_:) creates a new multiset with only the elements common to a multiset and another multiset or sequence.
  • symmetricDifference(_:) creates a new multiset with the elements that are in either a multiset or another multiset or sequence, but not in both.
  • subtracting(_:) creates a new multiset with the elements of a multiset that are not also in another multiset or sequence.

  • Note

    Note that when multisets have more than one of the same element some of these operations may not be as obvious as with sets. For example if: AAB = Multiset([A:2, B:1]) and ABC = Multiset([A:1, B:1, C:1]) then AAB.symmetricDifference(ABC) is Multiset([A:1, C:1])

    You can modify a multiset in place by using these mutating methods: formUnion(_:), formIntersection(_:), formSymmetricDifference(_:), and subtract(_:).

    Multiset operations are not limited to use with other multisets. You can perform many operations with sets, arrays or any sequence with the same Element type:

    let word = Multiset(Array("SINS"))
    word is now ["S":2, "I":1, "N":1] although Multisets are not ordered so may
    be a different order.
    
    let scrabbleHand: [Character] = ["MISSING"]
    
    // Tests whether the characters of the word SINS can be found in the
     // array of characters MISSING:
    print(word.isSubset(of: scrabbleHand) )
    // Prints "true"
    
    // Performs an intersection with an Array<Int>
    let primes: Multiset = [2, 3, 5, 7, 11, 13, 17, 19, 23]
    let favoriteNumbers = [5, 7, 15, 21]
    print(primes.intersection(favoriteNumbers))
    // Prints "[5, 7]"
    

    Other reading

    Because Multiset has some similarity with both Set and Dictionary, reading the documentation or source for those may also be useful:

    https://github.com/apple/swift/blob/master/stdlib/public/core/Set.swift https://github.com/apple/swift/blob/master/stdlib/public/core/Dictionary.swift

    See more

    Declaration

    Swift

    public struct Multiset<Element> where Element : Hashable
  • MultisetIndex

    Defines an index into a Multiset

    See more

    Declaration

    Swift

    public struct MultisetIndex<Element> where Element : Hashable