swift5.x 集合(Set)的基本操作

//
//  ViewController3.swift
//  swiftT
//
//  Created by wjwdive
//  Copyright © 2020 wjwdive. All rights reserved.
//

import UIKit

struct Person {
    var name: String
    var age: Int
}
//准守 Hashable 协议, 不实现该方法会报错:Type 'Person' does not conform to protocol 'Hashable'
extension Person: Hashable {
    func hash(into hasher: inout Hasher) {
        hasher.combine(age)
        hasher.combine(name)
    }
}

extension Person: Equatable {
    static func ==(lhs: Self, rhs: Person) -> Bool {
        return lhs.name == rhs.name
    }
}

class ViewController3: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        //创建Set
        let person: Set<Person> = [Person(name: "Jarvis", age: 18)]
        print(person)
        
        // 遍历Set
        //可以使用For-in 遍历 Set
        //因为Set 是无序的,如果需要顺序遍历Set,使用 sorted() 方法。
        
        //访问Set
       //Set.count
       //Set.isEmpty()
       
       //Set 添加元素
       //insert(_:)  添加一个元素到Set
       //update(with:) 如果已经有相等的元素,替换为新元素。如果Set 中没有,则插入
       
       //Set 移除元素
       //filter(_:) 返回一个新的Set, 新Set的元素是Set符合条件的元素
       //remove(_:) 从Set中移除一个s元素。如果元素是Set的成员就移除它,并且返回移除的值,如果集合中没有这个元素就返回你了
       //removeAll()   移除所有元素
       //removeFirst()  移除Set 的第一个元素,并不是第一个放入的元素,而是 hash后排序的第一个元素
       
        
        let course: Set = ["Math", "English", "History"]
        for c in course {
            print(c)
        }
        
        for cs in course.sorted() {
            print(cs)
        }
        
        var personsSet: Set<Person> = [Person(name: "Jarvis", age: 18), Person(name: "lisi", age: 18)]
        personsSet.update(with: Person(name:"Harvis", age: 20))
        //移除集合首部的元素
        personsSet.removeFirst()
        print("移除集合首部的元素 ", personsSet)
            
        print("filter : ", personsSet.filter({$0.age > 20}))
        
       
        //集合的计算
        //交,差(对称差集,所有属于A和B切不属于A和B的交集的元素),并,补(所有属于A但不属于B的元素)
        let a: Set<Character> = ["A", "B", "C"]
        let b: Set<Character> = ["B", "E", "F", "G"]
        print("a 交 b", a.intersection(b))
        print("a 并 b", a.union(b))
        print("a 对称差集 b", a.symmetricDifference(b))
        print("a 补 b", a.subtracting(b))

        print("a b, 有无相同元素", a.isDisjoint(with: b))
        
        //Set 的判断方法
        //isSubSet(of:) 判断是否是另一个Set或者Sequence的子集
        //isSuperSet(of:)   判断是否是另一个Set 或者 Sequence 的超集
        //isStrictSubset(of:) isStrictSuperset(of:)  判断是否是另一个Set的子集或者超集,但是又不等于另一个Set
        //isDisjoint(with:) 判断两个Set 是否有公共元素,如果没有返回True, 如果有返回false
        
        let smallSet: Set = [1, 2, 3]
        let bigSet: Set = [1, 2, 3, 4]
        print(smallSet.isSubset(of: bigSet))
        print(bigSet.isSuperset(of: smallSet))
        print(smallSet.isStrictSubset(of: bigSet))
        print(bigSet.isStrictSuperset(of: smallSet))
        print(smallSet.isDisjoint(with: bigSet))
        
        //实现自己的集合算法
        //给定一个集合,返回该集合的所有子集
        
        let sett: Set = ["A", "B", "C"]
        let subSets = getSubsets(sett)
           for subSet in subSets {
                print(subSet)
            }
           
    }
    
    //求给定集合的所有子集, 1、位法, 局限:只能计算出集合中元素个数小于计算机位数的集合的所有子集,超出计算机位数,无法用该方法
    func getSubsets<T>(_ set: Set<T>) -> Array<Set<T>> {
        let count = 1 << set.count  // 左移count位, 2的 conut 次方个子集
        let elements = Array(set)   // 包含所有set元素的array
        var subsets = [Set<T>]()    // 可变数组,存储 set的子集
        for i in 0..<count {        // 针对每个子集的值 写入到待返回数组,每次的循环次数依次是 0, 1, 10, 11, 110,111,。。。 1代表对应数组位选中,0 代表不选中
            var subset = Set<T>()   // 用来保存子集的临时变量
            for j in 0..<elements.count {   // 针对已知集合中的每个元素,右移并和1做与操作,然后和1比较,结果为1 存入临时变量 subset, 否则不存入
                if((i >> j) & 1) == 1{  // 把 i 依次移位,
                    subset.insert(elements[j])
                }
            }
            subsets.append(subset)
        }
        return subsets
    }
    
   //求给定集合的左右子集, 2、递归法 每个元素构成子集的时候都有入选子集合不入选子集两种选择
    func getSubsetsRescue<T>(set: Set<T>) -> Array<Set<T>> {
        let elements = Array(set)
        return getSubsetPart(elements, index:elements.count - 1, count:elements.count )
    }
    
    
    func getSubsetPart<T>(_ elements: Array<T>, index: Int, count: Int) -> Array<Set<T>>{
        var subsets = Array<Set<T>>()
        //只有一个元素时
        if index == 0 {
            subsets.append(Set<T>())//添加空集到子集合数组
            var subset = Set<T>()
            subset.insert(elements[0])//构建只有一个元素的集合
            subsets.append(subset)//添加一个元素集合到子集合数组
            return subsets
        }
        
        //递归调用
        subsets = getSubsetPart(elements, index: index - 1, count: count)
        //
        for subset in subsets {
            var subsetWithCurrent = Set(subset)
            subsetWithCurrent.insert(elements[index])
            subsets.append(subsetWithCurrent)
        }
        return subsets
    }

    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destination.
        // Pass the selected object to the new view controller.
    }
    */

}

原文地址:https://www.cnblogs.com/wjw-blog/p/12915219.html