Swift数组过滤问题:如何移除与另一数组flavour匹配的元素?
问题:过滤冰淇淋数组,排除指定口味元素
我需要匹配两个不同数组中的flavour属性,创建一个新数组,包含shopIcecreams中所有元素,排除那些与myIcecreams中flavour属性匹配的元素(例如此处巧克力口味的元素需被移除)。
Icecream 结构体定义
struct Icecream: Encodable, Decodable { var color: String var flavour: String }
数组定义
var myIcecreams = [ Icecream(color: "yellow", flavour: "banana"), Icecream(color: "green", flavour: "mint"), Icecream(color: "white", flavour: "banana"), Icecream(color: "brown", flavour: "chocolate") ]
var shopIcecreams = [ Icecream(color: "red", flavour: "strawberry"), Icecream(color: "purple", flavour: "blueberry"), Icecream(color: "green", flavour: "pistachio"), Icecream(color: "white", flavour: "chocolate") ]
我尝试了以下代码但未成功:
let filteredIcecreams = shopIcecreams.filter { newIcecream in myIcecreams.contains { myIcecream in newIcecream.flavour != myIcecream.flavour } }
请问我的代码哪里出错了?
错误原因分析
你的filter逻辑完全搞反了:myIcecreams.contains只要找到任意一个口味不匹配的元素就会返回true,这导致所有shopIcecreams里的元素都会被保留——哪怕某个元素的口味在myIcecreams里存在,只要数组里还有其他不同口味的元素,contains就会返回true,根本起不到过滤作用。
举个例子,shopIcecreams里的巧克力口味冰淇淋,myIcecreams里虽然有巧克力,但也有香蕉、薄荷等其他口味,所以newIcecream.flavour != myIcecream.flavour会在遇到香蕉的时候成立,contains返回true,这个巧克力元素就被错误地保留了。
正确写法
写法一:修正逻辑判断
把判断条件改成:当前冰淇淋的口味在myIcecreams中完全没有匹配项,才将其保留:
let filteredIcecreams = shopIcecreams.filter { shopIcecream in !myIcecreams.contains { myIcecream in shopIcecream.flavour == myIcecream.flavour } }
写法二:用Set优化性能(推荐)
如果数组元素数量较多,反复调用contains会产生O(n*m)的时间复杂度。先把myIcecreams的口味提取成Set,再判断元素口味是否不在这个集合中,时间复杂度可以降到O(n+m):
let myFlavours = Set(myIcecreams.map(\.flavour)) let filteredIcecreams = shopIcecreams.filter { !myFlavours.contains($0.flavour) }
两种写法最终都会正确过滤掉shopIcecreams中的巧克力口味元素,得到包含草莓、蓝莓、开心果的数组。
内容的提问来源于stack exchange,提问作者Joseph August
相关产品推荐
相关产品推荐

