Swift 中根据索引范围创建新数组
在 Swift 中,你可以使用 ArraySlice 类型创建一个数组。以下示例将展示如何使用 ArraySlice 类型。你也可以创建一个扩展来定义下标方法。
示例 1
在下面的示例中,我们创建了一个包含 0 到 9 值的数字数组,然后创建了一个从 startIndex 到 endIndex(不包含 endIndex)的索引范围。使用此范围,我们可以生成原始数组的 ArraySlice。最后,我们将使用 Array 初始化器将 ArraySlice 转换为数组并打印结果。
import Foundation let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] let startIndex = 3 // inclusive let endIndex = 8 // exclusive let slice = numbers[startIndex..<endIndex] // return an ArraySlice<Int> let newArray = Array(slice) // converts ArraySlice<Int> to [Int] print("Original array: \(numbers)") print("New array: \(newArray)")
输出
Original array: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] New array: [3, 4, 5, 6, 7]
请注意,startIndex 是包含的,而 endIndex 是不包含的。这意味着新数组将包含从 startIndex 开始的原始数组中的元素,但不包括 endIndex。
示例 2
假设你有一个 Student 对象数组,其中每个学生都有姓名和年龄。假设你想要获取一个包含 25 到 35 岁学生的新数组。要获取这些学生,可以使用索引范围。
算法
步骤 1 − 在此示例中,我们使用 firstIndex(where:) 方法查找年龄大于或等于 25 的第一个学生的索引。我们使用 nil 合并运算符 ?? 来提供一个默认值 0,如果 firstIndex 方法返回 nil(即,如果没有年龄为 25 或更大的学生)。
步骤 2 − 我们做同样的事情来查找年龄大于 35 的第一个学生的索引。如果不存在年龄超过 35 岁的学生,我们在这里使用 student 数组的 endIndex 属性。
步骤 3 − 最后,我们通过使用我们计算的起始和结束索引切片原始学生的数组,然后使用 Array 初始化器将生成的 ArraySlice 转换为数组来创建一个新数组。
步骤 4 − 生成的 filteredStudents 数组将只包含年龄在 25 到 35 岁之间的学生,顺序与他们在原始学生数组中出现的顺序相同。
步骤 5 − 请记住,索引范围是半开区间,这意味着年龄为 25 的学生将包含在新数组中,但年龄为 35 的学生将不会包含(假设原始数组中存在这样的学生)。
代码如下
import Foundation struct Student { let name: String let age: Int } let students = [ Student(name: "Alice", age: 30), Student(name: "Bob", age: 25), Student(name: "Charlie", age: 35), Student(name: "Dave", age: 40), Student(name: "Eve", age: 20), Student(name: "Frainke", age: 33) ] let startingIndex = students.firstIndex { $0.age >= 25 } ?? 0 let endingIndex = students.firstIndex { $0.age > 35 } ?? students.endIndex let filteredStudents = Array(students[startingIndex..<endingIndex]) print("Original Student Names: - ") students.forEach { student in print(student.name) } print("Filtered Student Names: - ") filteredStudents.forEach { student in print(student.name) }
输出
Original Student Names: - Alice Bob Charlie Dave Eve Frainke Filtered Student Names: - Alice Bob Charlie
推荐方法
还有一种高效且安全的方法可以根据索引范围创建新数组。在这种方法中,你可以创建如下所示的扩展 −
示例
import Foundation extension Array { public subscript(safe bounds: Range<Int>) -> ArraySlice<Element> { if bounds.lowerBound > count { return [] } let lower = Swift.max(0, bounds.lowerBound) let upper = Swift.max(0, Swift.min(count, bounds.upperBound)) return self[lower..<upper] } public subscript(safe lower: Int?, _ upper: Int?) -> ArraySlice<Element> { let lower = lower ?? 0 let upper = upper ?? count if lower > upper { return [] } return self[safe: lower..<upper] } } let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] print("Original array: \(numbers)") print(numbers[safe: 0..<1]) print(numbers[safe: 5..<100]) print(numbers[safe: -5..<50]) print(numbers[safe: 5, 10])
输出
Original array: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [0] [5, 6, 7, 8, 9] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [5, 6, 7, 8, 9]
结论
在 Swift 中,根据一组索引创建一个新数组是很常见的做法,根据你的需求,你可以采取各种方法。
要根据部分开区间索引构造一个新数组,请使用带有原始数组切片的 Array 初始化器。虽然这是一种清晰简洁的方法,但是你必须手动计算起始和结束索引。
为了提供更实用的创建数组切片的方法,你可以选择对 Array 使用扩展。使用这种更灵活的方法,你可以使用包含式、排除式或部分开区间索引创建切片。