Swift中多级数组读写及指定位置插入标识的实现与展示
咱们先明确:多级数组就是嵌套数组,比如二维数组 [[T]](T可以是任意类型),甚至更深的嵌套结构(比如三维数组 [[[Int]]])。下面分追加和读取两种场景来具体说明:
一、追加元素
多级数组的追加分两种常见情况,对应不同的实现方式:
1. 给顶层数组追加子数组
直接用数组的 append(_:) 方法即可,比如我们有一个存储字符串的二维数组:
var multiArray: [[String]] = [["a", "b"], ["c", "d"]] // 追加一个新的子数组 multiArray.append(["e", "f"]) // 此时multiArray变为:[["a","b"], ["c","d"], ["e","f"]]
2. 给现有子数组追加元素
因为Swift的数组是值类型,直接通过索引获取子数组后修改的话,只会修改副本,不会影响原数组。正确的做法是先取出子数组,修改后再赋值回去:
// 给第一个子数组(索引0)追加元素"g" var subArray = multiArray[0] subArray.append("g") multiArray[0] = subArray // 现在multiArray[0]变成:["a","b","g"]
或者更简洁的写法(Swift会自动处理值类型的拷贝逻辑,最终效果一致):
multiArray[0].append("g")
二、读取元素
读取多级数组需要通过多层索引访问,但一定要注意索引越界问题——直接访问非法索引会导致崩溃,所以推荐先判断索引合法性:
1. 不安全的直接读取(不推荐)
let element = multiArray[0][1] // 获取第一个子数组的第二个元素,即"b"
2. 安全读取(推荐)
利用数组的 indices 属性判断索引是否存在:
if multiArray.indices.contains(0), multiArray[0].indices.contains(1) { let element = multiArray[0][1] print(element) // 输出"b" } else { print("索引越界,无法读取元素") }
如果是更深的嵌套数组,只需要多一层索引判断即可。
这个需求的核心是在遍历原数组时按规则插入新元素,直接修改原数组会导致遍历索引混乱,所以最好的方式是创建新数组存储结果。下面分实现步骤和循环展示来讲解:
一、插入"Yes"的实现
假设你的 UsersList 是一个自定义模型,比如:
struct UsersList { let name: String // 其他业务属性... }
方案1:使用[Any]混合类型数组(快速实现)
适合快速验证需求的场景,缺点是丢失类型信息:
let originalUsers: [UsersList] = [/* 你的原数组数据 */] var resultArray: [Any] = [] for (index, user) in originalUsers.enumerated() { // 先添加当前用户 resultArray.append(user) // 每添加60个用户后插入"Yes"(index从0开始,所以index+1等于60时就是第60个元素) if (index + 1) % 60 == 0 { resultArray.append("Yes") } }
处理后,resultArray 就会按照 [user1,…user60,"Yes",user61,…] 的格式排列。
方案2:使用枚举实现类型安全(推荐)
通过枚举统一两种元素类型,避免后续类型转换错误:
enum ListItem { case user(UsersList) case marker(String) } var resultArray: [ListItem] = [] for (index, user) in originalUsers.enumerated() { resultArray.append(.user(user)) if (index + 1) % 60 == 0 { resultArray.append(.marker("Yes")) } }
这种方式更符合Swift的类型安全原则,后续处理也更清晰。
二、循环展示元素
对应上面的两种方案,循环展示的代码也略有不同:
对应方案1([Any]数组)
for item in resultArray { if let user = item as? UsersList { print("用户:\(user.name)") } else if let marker = item as? String { print(marker) // 输出"Yes" } }
对应方案2(枚举数组)
for item in resultArray { switch item { case .user(let user): print("用户:\(user.name)") case .marker(let text): print(text) } }
这种switch的方式更安全,编译器会自动检查所有可能的元素类型,避免遗漏。
内容的提问来源于stack exchange,提问作者kamenr

