You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将嵌套数组按子数组末尾元素过滤为三个数组的最优方法

问题

我有如下嵌套数组:

var masterArray = [
   ["String", "String", "String", "1"],
   ["String", "String", "String", "2"],
   ["String", "String", "String", "3"],
   ...
]

每个子数组的最后一个元素是字符串类型的整数。请问将该主数组按子数组末尾元素过滤为三个数组的最高效方法是什么?

我目前可以通过以下方式实现:

var filteredArray1 = [[String]]()
var filteredArray2 = [[String]]()
var filteredArray3 = [[String]]()

for anArray in masterArray {
   if anArray[3] == "1" {
      filteredArray1.append(anArray) 

   } else if anArray[3] == "2" {
      filteredArray2.append(anArray) 

   } else if anArray[3] == "3" {
      filteredArray3.append(anArray) 

   } 
}

但我认为应该有更高效的实现方式,比如使用filter或NSPredicate?只是不知道如何定位子数组的最后一个元素。

补充说明
在另一个不相关的场景中,我有一组CoreData实体tagRecords,已知每个实体都有dateStart属性,我可以通过NSPredicate轻松过滤:

let currentPred = NSPredicate(format: "dateStart >= %@ && dateStart <= %@", argumentArray: [currentMonth.startOfMonth(), currentMonth.endOfMonth()])
                
let filteredRecords = tagRecords.filter { currentPred.evaluate(with: $0) }
高效实现方案

方法1:使用filter分三次过滤

这种方式代码简洁易读,利用Swift原生的filter方法结合last属性直接筛选:

let filteredArray1 = masterArray.filter { $0.last == "1" }
let filteredArray2 = masterArray.filter { $0.last == "2" }
let filteredArray3 = masterArray.filter { $0.last == "3" }
  • 优势:无需硬编码索引(比如原代码中的anArray[3],如果子数组长度变化会触发越界错误),代码逻辑直观。
  • 局限:会遍历原数组三次,数组规模较大时性能不如单次遍历方案。

方法2:使用reduce单次遍历分组

如果追求最高性能(尤其适用于大型数组),推荐用reduce单次完成分组,避免重复遍历:

let result = masterArray.reduce(into: ([], [], [])) { partial, subArray in
    guard let lastElement = subArray.last else { return }
    switch lastElement {
    case "1": partial.0.append(subArray)
    case "2": partial.1.append(subArray)
    case "3": partial.2.append(subArray)
    default: break
    }
}

let filteredArray1 = result.0
let filteredArray2 = result.1
let filteredArray3 = result.2
  • 优势:仅遍历原数组一次,性能和你原来的循环相当,但写法更规范,且通过last属性避免了索引越界风险。

方法3:用NSPredicate实现(不推荐)

虽然可以用NSPredicate实现,但对于Swift原生数组来说,语法繁琐且性能不如原生方法:

let pred1 = NSPredicate(format: "lastObject == %@", "1")
let filteredArray1 = masterArray.filter { pred1.evaluate(with: $0) }
  • 原因:NSPredicate更多为Objective-C对象设计,Swift原生的filter/reduce在处理原生数组时更高效、易读。

性能选择建议

  • 数组规模较小时:优先选filter方案,代码简洁易维护。
  • 数组规模较大时:选reduce单次遍历方案,性能最优。

内容的提问来源于stack exchange,提问作者grep

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 00:37:46