Swift_数据类型_Array/Set

Swift 中 Array 的简单介绍,方便初学者快速入门

目录

  1. 基础概念
  2. 声明和初始化
  3. 数组属性
  4. 数组操作
  5. 数组遍历
  6. 数组方法
  7. 数组切片
  8. 多维数组
  9. 性能优化
  10. 安全性和错误处理
  11. 高级用法
  12. 实际应用示例
  13. 最佳实践
  14. 常见陷阱

基础概念

Array 是 Swift 中的泛型集合类型,用于存储有序的元素集合。

特点

  • 有序性:元素按照插入顺序排列
  • 可重复:允许存储重复的元素
  • 类型安全:编译时类型检查
  • 可变性:使用 var 声明可修改,使用 let 声明不可修改

性能特征

  • 随机访问:O(1) 时间复杂度
  • 插入/删除:O(n) 时间复杂度(在末尾操作除外)
  • 内存效率:连续内存存储

声明和初始化

基本语法

// 显式类型声明
let ints: Array<Int> = [1, 2, 3, 4, 5]
let strings: [String] = ["one", "two", "three"]

// 类型推断
let numbers = [1, 2, 3, 4, 5]  // 自动推断为 [Int]
let words = ["hello", "world"]  // 自动推断为 [String]

空数组初始化

var emptyInts: [Int] = []
var emptyStrings = [String]()
var emptyDoubles = Array<Double>()

重复元素初始化

let repeated = Array(repeating: 0, count: 5)  // [0, 0, 0, 0, 0]
let repeatedStrings = Array(repeating: "default", count: 3)  // ["default", "default", "default"]

范围初始化

let rangeArray = Array(1...10)  // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let rangeArray2 = Array(1..<6)   // [1, 2, 3, 4, 5]

数组属性

基本属性

let sampleArray = [1, 2, 3, 4, 5]

print(sampleArray.count)    // 5 - 元素个数
print(sampleArray.isEmpty)  // false - 是否为空
print(sampleArray.capacity) // 当前分配的容量

元素访问

// 安全访问(返回可选值)
print(sampleArray.first)   // Optional(1)
print(sampleArray.last)    // Optional(5)

// 强制访问(需要确保数组不为空)
print(sampleArray.first!)  // 1
print(sampleArray.last!)   // 5

// 索引访问
print(sampleArray[2])      // 3

数组操作

添加元素

var mutableArray = [1, 2, 3]

// 在末尾添加
mutableArray.append(4)                    // [1, 2, 3, 4]
mutableArray += [5, 6]                    // [1, 2, 3, 4, 5, 6]

// 在指定位置插入
mutableArray.insert(0, at: 0)             // [0, 1, 2, 3, 4, 5, 6]

删除元素

var deleteArray = [1, 2, 3, 4, 5, 6]

// 删除指定索引的元素
let removed = deleteArray.remove(at: 2)    // 返回被删除的元素 3
print(deleteArray)                         // [1, 2, 4, 5, 6]

// 删除第一个元素
let firstRemoved = deleteArray.removeFirst()  // 返回 1
print(deleteArray)                             // [2, 4, 5, 6]

// 删除最后一个元素
let lastRemoved = deleteArray.removeLast()     // 返回 6
print(deleteArray)                             // [2, 4, 5]

// 删除所有元素
deleteArray.removeAll()
print(deleteArray)                             // []

替换元素

var replaceArray = [1, 2, 3, 4, 5]
replaceArray[2] = 10                       // [1, 2, 10, 4, 5]

// 替换范围
replaceArray[1...3] = [20, 30, 40]        // [1, 20, 30, 40, 5]

数组遍历

基本遍历

let traverseArray = ["apple", "banana", "orange", "grape"]

// for-in 循环
for item in traverseArray {
    print(item)
}

// 带索引的遍历
for (index, item) in traverseArray.enumerated() {
    print("索引 \(index): \(item)")
}

高级遍历

// 使用 indices 遍历索引
for index in traverseArray.indices {
    print("索引 \(index): \(traverseArray[index])")
}

// 使用 stride 遍历
for index in stride(from: 0, to: traverseArray.count, by: 2) {
    print("偶数索引 \(index): \(traverseArray[index])")
}

// 反向遍历
for item in traverseArray.reversed() {
    print(item)
}

// 带索引的反向遍历
for (index, item) in traverseArray.enumerated().reversed() {
    print("反向索引 \(index): \(item)")
}

数组方法

排序

let methodArray = [3, 1, 4, 1, 5, 9, 2, 6]

// 初始排序
var sortArray = methodArray
sortArray.sort()                           // 升序排序
sortArray.sort(by: <)                      // 升序排序
sortArray.sort(by: >)                      // 降序排序

// 返回新数组的排序
let sortedArray = methodArray.sorted()     // 不改变原数组

查找

let searchArray = ["apple", "banana", "orange", "grape"]

// 查找元素是否存在
let containsApple = searchArray.contains("apple")  // true

// 查找元素索引
if let index = searchArray.firstIndex(of: "banana") {
    print("banana 的索引: \(index)")       // 1
}

// 查找满足条件的第一个元素
if let firstLong = searchArray.first(where: { $0.count > 5 }) {
    print("第一个长度大于5的元素: \(firstLong)")  // "banana"
}

函数式编程方法

let filterArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// 过滤
let evenNumbers = filterArray.filter { $0 % 2 == 0 }  // [2, 4, 6, 8, 10]

// 映射
let doubled = filterArray.map { $0 * 2 }              // [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

// reduce
let sum = filterArray.reduce(0, +)                    // 55
let product = filterArray.reduce(1, *)                // 3628800

// flatMap
let nestedArray = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
let flattened = nestedArray.flatMap { $0 }            // [1, 2, 3, 4, 5, 6, 7, 8, 9]

数组切片

基本切片

let sliceArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

let firstThree = sliceArray[0..<3]         // [0, 1, 2]
let lastThree = sliceArray[7...9]          // [7, 8, 9]
let middle = sliceArray[3...6]             // [3, 4, 5, 6]

使用 prefix 和 suffix

let prefix3 = sliceArray.prefix(3)         // [0, 1, 2]
let suffix3 = sliceArray.suffix(3)         // [7, 8, 9]

// 条件切片
let evenPrefix = sliceArray.prefix { $0 % 2 == 0 }  // [0]

多维数组

二维数组

let matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

print(matrix[0])        // [1, 2, 3]
print(matrix[1][1])     // 5

创建多维数组

var emptyMatrix = Array(repeating: Array(repeating: 0, count: 3), count: 3)

遍历多维数组

for (rowIndex, row) in matrix.enumerated() {
    for (colIndex, element) in row.enumerated() {
        print("matrix[\(rowIndex)][\(colIndex)] = \(element)")
    }
}

性能优化

预分配容量

var optimizedArray = [Int]()
optimizedArray.reserveCapacity(1000)       // 预分配1000个元素的容量

批量操作

var batchArray = [Int]()
batchArray.reserveCapacity(100)

// 批量添加(比逐个添加更高效)
batchArray.append(contentsOf: 1...100)

延迟计算

let lazyArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let lazyResult = lazyArray.lazy
    .filter { $0 % 2 == 0 }
    .map { $0 * $0 }
    .prefix(3)

print(Array(lazyResult))  // [4, 16, 36]

安全性和错误处理

边界检查

let safeArray = [1, 2, 3, 4, 5]

// 安全的索引访问
if safeArray.indices.contains(10) {
    let element = safeArray[10]
} else {
    print("索引超出范围")
}

可选绑定

if let firstElement = safeArray.first {
    print("第一个元素: \(firstElement)")
}

if let lastElement = safeArray.last {
    print("最后一个元素: \(lastElement)")
}

条件删除

var conditionalArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// 删除所有偶数
conditionalArray.removeAll { $0 % 2 == 0 }
print(conditionalArray)  // [1, 3, 5, 7, 9]

高级用法

数组比较

let array1 = [1, 2, 3]
let array2 = [1, 2, 3]
let array3 = [1, 2, 4]

print(array1 == array2)  // true
print(array1 == array3)  // false

数组连接

let arrayA = [1, 2, 3]
let arrayB = [4, 5, 6]
let combined = arrayA + arrayB  // [1, 2, 3, 4, 5, 6]

自定义扩展

// 数组分块
extension Array {
    func chunked(into size: Int) -> [[Element]] {
        return stride(from: 0, to: count, by: size).map {
            Array(self[$0..<Swift.min($0 + size, count)])
        }
    }
}

let chunkArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let chunks = chunkArray.chunked(into: 3)  // [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]

// 数组去重(保持顺序)
extension Array where Element: Hashable {
    func removingDuplicates() -> [Element] {
        var seen = Set<Element>()
        return filter { seen.insert($0).inserted }
    }
}

let orderedArray = [1, 2, 2, 3, 3, 3, 4, 5, 5]
let uniqueOrdered = orderedArray.removingDuplicates()  // [1, 2, 3, 4, 5]

实际应用示例

学生成绩管理

struct Student {
    let name: String
    let score: Int
}

let students = [
    Student(name: "Alice", score: 85),
    Student(name: "Bob", score: 92),
    Student(name: "Charlie", score: 78),
    Student(name: "Diana", score: 95),
    Student(name: "Eve", score: 88)
]

// 按成绩排序
let sortedStudents = students.sorted { $0.score > $1.score }

// 计算平均分
let averageScore = students.map { $0.score }.reduce(0, +) / students.count

购物车示例

struct Product {
    let name: String
    let price: Double
    let quantity: Int
}

var cart = [
    Product(name: "苹果", price: 5.0, quantity: 3),
    Product(name: "香蕉", price: 3.0, quantity: 2),
    Product(name: "橙子", price: 4.0, quantity: 1)
]

// 计算总价
let totalPrice = cart.map { $0.price * Double($0.quantity) }.reduce(0, +)

// 添加商品
cart.append(Product(name: "葡萄", price: 8.0, quantity: 1))

// 移除特定商品
cart.removeAll { $0.name == "香蕉" }

数据分析

let dataPoints = [23, 45, 67, 89, 12, 34, 56, 78, 90, 11]

// 统计信息
let minValue = dataPoints.min() ?? 0
let maxValue = dataPoints.max() ?? 0
let sumValue = dataPoints.reduce(0, +)
let average = Double(sumValue) / Double(dataPoints.count)

// 数据分组
let grouped = Dictionary(grouping: dataPoints) { $0 / 20 }

最佳实践

1. 类型安全

  • 始终使用明确的类型声明
  • 利用 Swift 的类型推断功能

2. 性能考虑

  • 对于频繁修改的数组,使用 var 声明
  • 预分配容量以提高性能
  • 使用批量操作而不是循环

3. 内存管理

  • 及时清理不需要的数组引用
  • 避免循环引用

4. 错误处理

  • 始终检查数组边界
  • 使用可选绑定进行安全访问

5. 代码可读性

  • 使用有意义的变量名
  • 适当使用注释
  • 遵循 Swift 编码规范

常见陷阱

1. 修改常量数组

// 错误示例
let constantArray = [1, 2, 3]
// constantArray.append(4)  // 编译错误

// 正确做法
var mutableArray = [1, 2, 3]
mutableArray.append(4)  // 正确

2. 数组越界

// 错误示例
let boundsArray = [1, 2, 3]
// let element = boundsArray[5]  // 运行时错误

// 正确做法
if boundsArray.indices.contains(5) {
    let element = boundsArray[5]
} else {
    print("索引超出范围")
}

3. 空数组操作

// 错误示例
let emptyArray: [Int] = []
// let first = emptyArray[0]  // 运行时错误

// 正确做法
if let first = emptyArray.first {
    print("第一个元素: \(first)")
} else {
    print("数组为空")
}

总结

Swift Array 是一个功能强大且类型安全的集合类型,提供了丰富的操作方法和函数式编程特性。通过合理使用这些功能,可以编写出高效、安全、易读的代码。

关键要点:

  • 理解数组的基本概念和性能特征
  • 掌握各种初始化方法
  • 熟练使用数组的增删改查操作
  • 学会使用函数式编程方法
  • 注意数组的安全性和边界检查
  • 遵循最佳实践,避免常见陷阱

Swift 的 Set(集合)是一种无序且不重复的元素集合,常用于去重、集合运算等场景。

1. Set 的声明与初始化

// 声明一个空的 Set
var emptySet = Set<Int>()

// 使用数组字面量初始化 Set(自动去重)
let numberSet: Set = [1, 2, 3, 4, 5, 2, 3] // 结果:[1, 2, 3, 4, 5]

2. 基本操作

var fruits: Set = ["Apple", "Banana", "Orange"]

// 添加元素
fruits.insert("Grape")

// 删除元素
fruits.remove("Banana")

// 判断是否包含某元素
fruits.contains("Apple") // true

// 获取元素个数
fruits.count

// 判断是否为空
fruits.isEmpty

3. 遍历 Set

for fruit in fruits {
    print(fruit)
}

4. Set 的常用集合运算

let setA: Set = [1, 2, 3, 4]
let setB: Set = [3, 4, 5, 6]

// 交集
let intersection = setA.intersection(setB) // [3, 4]

// 并集
let union = setA.union(setB) // [1, 2, 3, 4, 5, 6]

// 差集
let subtracting = setA.subtracting(setB) // [1, 2]

// 对称差集(不属于双方的元素)
let symmetricDiff = setA.symmetricDifference(setB) // [1, 2, 5, 6]

5. Set 的比较

let setC: Set = [1, 2]
let setD: Set = [1, 2, 3, 4]

setC.isSubset(of: setD)      // true,setC 是 setD 的子集
setD.isSuperset(of: setC)    // true,setD 是 setC 的超集
setC == setD                 // false

6. Set 的常见应用场景

  • 数组去重:let uniqueArray = Array(Set(array))
  • 判断两个集合是否有交集:setA.isDisjoint(with: setB)

7. 注意事项

  • Set 元素必须遵循 Hashable 协议(大多数基础类型都已遵循)。
  • Set 是无序的,不能通过下标访问元素。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容