Swift:如何用一行代码移除数组中含指定字符串的元素?效率如何
Swift 一行代码实现数组过滤及效率对比
需求回顾
给定字符串数组array1和过滤条件数组array2,需要移除array1中包含array2任意元素的项:
var array1 = ["first.food", "second.easy.good", "third.long.bad", "4.bad.apple", "cinco.Thank You!"] let array2 = ["food", "bad"]
期望结果:array1 = ["second.easy.good", "cinco.Thank You!"]
一行代码实现
完全可以用一行代码完成需求,利用filter结合contains(where:)的短路特性:
array1 = array1.filter { !array2.contains(where: $0.contains) }
如果追求可读性,也可以写成更直白的版本:
array1 = array1.filter { item in !array2.contains(where: { item.contains($0) }) }
核心逻辑:对array1的每个元素,检查array2里是否存在任意子串被该元素包含,若不存在则保留该元素。
两种实现的效率差异
原循环过滤方式
for string in array2 { array1 = array1.filter { !$0.contains(string) } }
- 时间复杂度:最坏情况(所有元素都不被过滤)下为
O(N*M),其中N是array1初始长度,M是array2长度。每次循环都会遍历当前的array1并生成新数组,若前几次过滤能大幅缩短array1长度,后续循环成本会降低,但整体仍存在多次数组创建的额外开销。 - 内存开销:每次
filter都会生成新数组,多次触发内存分配与释放,数据量较大时这部分开销会很明显。
一行代码方式
- 时间复杂度:同样是
O(N*M),但每个array1元素只会被遍历一次,且contains(where:)是短路判断——只要找到匹配的子串就停止检查当前元素的剩余过滤条件,实际执行次数可能比最坏情况少。 - 内存开销:仅生成一次新数组,避免了多次内存分配的额外成本,数据量较大时优势更显著。
总结
多数场景下,一行代码的实现效率更高,同时代码更简洁易读。只有当array2长度极大,且前几次过滤能大幅削减array1长度时,原循环方式可能有微弱优势,但这种场景非常少见。
内容的提问来源于stack exchange,提问作者Ross Knipe
相关产品推荐
相关产品推荐

