第十五章 Swift 枚举

Swift的枚举也是一种数据类型,它是一组有共同特性的数据的集合,同样拥有属性和函数,可以指定类型,遵守协议。

// 定义星期的枚举:
enum DaysofaWeek {
    case Sunday
    case Monday
    case TUESDAY
    case WEDNESDAY
    case THURSDAY
    case FRIDAY
    case Saturday
}

var weekDay = DaysofaWeek.THURSDAY
weekDay = .THURSDAY
switch weekDay {
case .Sunday:
    print("星期天")
case .Monday:
    print("星期一")
case .TUESDAY:
    print("星期二")
case .WEDNESDAY:
    print("星期三")
case .THURSDAY:
    print("星期四")
case .FRIDAY:
    print("星期五")
case .Saturday:
    print("星期六")
}

// 星期四

枚举中定义的值(如 Sunday,Monday,……和Saturday)是这个枚举的成员值(或成员)。case关键词表示一行新的成员值将被定义。

注意: 和 C 和 Objective-C 不同,Swift 的枚举成员在被创建时不会被赋予一个默认的整型值。在上面的DaysofaWeek例子中,Sunday,Monday,……和Saturday不会隐式地赋值为0,1,……和6。相反,这些枚举成员本身就有完备的值,这些值是已经明确定义好的DaysofaWeek类型。

var weekDay = DaysofaWeek.THURSDAY 
weekDay的类型可以在它被DaysofaWeek的一个可能值初始化时推断出来。一旦weekDay被声明为一个DaysofaWeek,你可以使用一个缩写语法(.)将其设置为另一个DaysofaWeek的值:

var weekDay = .THURSDAY 
当weekDay的类型已知时,再次为其赋值可以省略枚举名。使用显式类型的枚举值可以让代码具有更好的可读性。

1. 相关值与原始值

Swift 中使用 enum 关键词来创建枚举并且把它们的整个定义放在一对大括号内。它可以拥有一个绑定的值(必须是常量),也可以没有。

相关值 原始值
不同数据类型 相同数据类型
实例: enum {10,0.8,"Hello"} 实例: enum {10,35,50}
值的创建基于常量或变量 预先填充的值
相关值是当你在创建一个基于枚举成员的新常量或变量时才会被设置,并且每次当你这么做得时候,它的值可以是不同的。 原始值始终是相同的相关值
enum Student{
    case Name(String)
    case Mark(Int,Int,Int)
}
var studDetails = Student.Name("Runoob")
var studMarks = Student.Mark(98,97,95)
switch studMarks {
case .Name(let studName):
    print("学生的名字是: \(studName)。")
case .Mark(let Mark1, let Mark2, let Mark3):
    print("学生的成绩是: \(Mark1),\(Mark2),\(Mark3)。")
}
/// 学生的成绩是: 98,97,95。

原始值

  1. 原始值可以是字符串,字符,或者任何整型值或浮点型值。每个原始值在它的枚举声明中必须是唯一的。
  2. 在原始值为整数的枚举时,不需要显式的为每一个成员赋值,Swift会自动为你赋值。当使用整数作为原始值时,隐式赋值的值依次递增1。如果第一个值没有被赋初值,将会被自动置为0。
enum Month: Int {
    case January = 1, February, March, April, May, June, July, August, September, October, November, December
}

let yearMonth = Month.May.rawValue
print("数字月份为: \(yearMonth)。") //数字月份为: 5。

2. 递归

相关值的枚举可以定义为递归类型,使用前需要添加关键字indirect

下面是利用Swift 枚举实现的链表的例子。

enum LinkList {
    case end
    indirect case node(value: Element, linkList: LinkList )
    
    var length: Int {
        var n = 0
        var node = self
        
        while case let .node(_,next) = node {
            n += 1
            node = next
        }
        return n
    }
    
    var elements: [Element] {
        var arr = [Element]()
        var node = self

        while case let .node(value,next) = node {
            arr.append(value)
            node = next
        }
        return arr
    }

    init(_ element: Element) {
        self = LinkList.node(value: element, linkList: .end)
    }
    
    init(_ elements: [Element]) {
        var node = LinkList.end
        for element in elements.reversed() {
            node = .node(value: element, linkList: node)
        }
        self = node
    }
}

// MARK: - 
extension LinkList {
    func print() {
        let elements = self.elements
        let count = elements.count
        var message = "LinkList: "
        
        switch count {
        case 0:
            message += "null"
        case 1:
            message = message + "\(elements.first!)"
        default:
            message = elements[0..<(count - 1)].reduce(message, { (res, item) -> String in
                return res + "\(item) -> "
            }) + "\(elements.last!)"
        }
        Swift.print(message)
    }
}

// MARK: - Add
extension LinkList {
    func add(_ element: Element) -> LinkList {
        if case let .node(value,next) = self {
            return .node(value: value, linkList: next.add(element))
        } else {
            return .node(value: element, linkList: .end)
        }
    }
    
    func add(_ elements: [Element]) -> LinkList {
        if case let .node(value,next) = self {
            if case .end = next {
                var node = LinkList.end
                for element in elements.reversed() {
                    node = .node(value: element, linkList: node)
                }
                return .node(value: value, linkList: node)
            } else {
                return .node(value: value, linkList: next.add(elements))
            }
        }
        return self
    }
    
    func add(_ linkList: LinkList) -> LinkList {
        if case let .node(value,next) = self {
            if case .end = next {
                return .node(value: value, linkList: linkList)
            } else {
                return .node(value: value, linkList: next.add(elements))
            }
        }
        return linkList
    }
    
    static func +(l1:LinkList, l2: LinkList) -> LinkList {
        return l1.add(l2)
    }
    
    static func +(l1:LinkList, element: Element) -> LinkList {
        return l1.add(element)
    }
    
    static func +(l1:LinkList, elements: [Element]) -> LinkList {
        return l1.add(elements)
    }
    
    static func +=(l1: inout LinkList, l2: LinkList) {
        l1 = l1.add(l2)
    }
    
    static func +=(l1: inout LinkList, element: Element) {
        l1 = l1.add(element)
    }
    
    static func +=(l1: inout LinkList, elements: [Element]) {
        l1 = l1.add(elements)
    }
}

// MARK: - Delete
extension LinkList {
    func delete(_ element: Element) -> LinkList {
        if case let .node(value, next) = self {
            if value == element {
                return next.delete(element)
            } else {
                return .node(value: value, linkList: next.delete(element))
            }
        }
        return self
    }
    
    func delete(at index: Int) -> LinkList {
        if index > 0, case let .node(value, next) = self {
            return .node(value: value, linkList: next.delete(at: index - 1))
        } else if index == 0, case let .node(_, next) = self {
            return next
        }
        
        return self
    }
    
    func removeLast() -> LinkList {
        return delete(at: length - 1)
    }
}

// MARK: - Insert
extension LinkList {
    func insert(_ element: Element, at index: Int) -> LinkList {
        guard index >= 0, index < length else { return self }
        
        if index > 0, case let .node(value,next) = self {
            return .node(value: value, linkList: next.insert(element, at: index - 1))
        }
        
        return .node(value: element, linkList: self)
    }
    
    func insert(_ elements: [Element], at index: Int) -> LinkList {
        guard index >= 0, index < length else { return self }
        
        if index > 0, case let .node(value,next) = self {
            return .node(value: value, linkList: next.insert(elements, at: index - 1))
        }
        
        var node = self
        for element in elements.reversed() {
            node = .node(value: element, linkList: node)
        }
        
        return node
    }
    
    func insert(_ linkList: LinkList, at index: Int) -> LinkList {
        guard index >= 0, index < length else { return self }

        if index > 0, case let .node(value,next) = self {
            return .node(value: value, linkList: next.insert(linkList, at: index - 1))
        }
        
        return linkList
    }
}

// MARK: - Subscript
// MARK: Index
extension LinkList {
    subscript (index: Int) -> Element? {
        set {
            self = setter(index, element: newValue)
        } get {
            return getter(index)
        }
    }
    
    private func setter(_ index: Int, element: Element?) -> LinkList {
        guard index >= 0, index < length else { return self }
        
        if index > 0, case let .node(value ,next) = self {
            return .node(value: value, linkList: next.setter(index - 1, element: element))
        } else if index == 0, case let .node(_,next) = self {
            if let element = element {
                return .node(value: element, linkList: next)
            } else {
                return .end
            }
        }
        
        return self
    }
    
    private func getter(_ index: Int) -> Element? {
        var n = 0
        var node = self
        
        while n >= index, case let .node(_,next) = node {
            n += 1
            node = next
        }
        
        
        if n >= index, case let .node(value: value, linkList: _) = node {
            return value
        }
        return nil
    }
}

// MARK: Range
extension LinkList {
    subscript (range: Range) -> LinkList {
        set {
            self = setter(range, linkList: newValue)
        } get {
            return getter(range)
        }
    }
    
    subscript (range: ClosedRange) -> LinkList {
        set {
            self = setter(range, linkList: newValue)
        } get {
            return getter(range)
        }
    }
    
    private func setter(_ range: T, linkList: LinkList) -> LinkList {
        let (max,min) = { () -> (Int,Int) in
            if let range = range as? Range {
                return (range.maxIndex, range.minIndex)
            } else if let range = range as? ClosedRange {
                return (range.upperBound, range.lowerBound)
            }
            fatalError("unsupport range!!")
        }()
        
        guard max > min else { return self }
        guard min >= 0, max < length else { return self }

        if min > 0, case let .node(value ,next) = self {
            let range = min - 1..(_ range: T) -> LinkList {
        let (max,min) = { () -> (Int,Int) in
            if let range = range as? Range {
                return (range.maxIndex, range.minIndex)
            } else if let range = range as? ClosedRange {
                return (range.upperBound, range.lowerBound)
            }
            fatalError("unsupport range!!")
        }()
        
        var node = self
        var res = LinkList.end
        var n = 0
        
        while case let .node(value, next) = node {
            defer {
                n += 1
                node = next
            }
            
            if min > n {
                continue
            } else if max >= n {
                res += value
            } else {
                break
            }
        }
        
        return res
    }
}

// MARK: Range Extension
extension Range where Bound == Int {
    var maxIndex: Int {
        return contains(upperBound) ? upperBound : (upperBound - 1)
    }
    
    var minIndex: Int {
        return contains(lowerBound) ? lowerBound : (lowerBound + 1)
    }
}

//        let linkList = LinkList([6,44,3])
//        let linkList = LinkList(3).add(5).add([6,7,8]).add(6).delete(6).delete(at: 2)
//        let linkList = LinkList(3).add([4,5,6]).insert(99, at: 3).insert([77,777], at: 3)
//        let linkList = LinkList(3).add([4,5,6]).insert(.init(19999), at: 3)
//        var linkList = LinkList(3).add([4,5,6])//.insert(.end, at: 3)
//        linkList[2] = 99
//        linkList[1] = nil
//        linkList.print()
        
//        let link2 = linkList[0..<3]
//        linkList[0...3].print()
//
//        link2.print()
  • 定义了一个枚举LinkList,有endnode两个case,其元素必须实现Comparable协议。
  • 该枚举支持单元素或数组初始化,添加删除插入等操作
  • 支持下标操作
  • 排序下次更新加上

你可能感兴趣的:(第十五章 Swift 枚举)