带权重可选属性对象与非可选对象的最优匹配方案问询
简洁实现:带权重的OptionalObject最优匹配方案
这个问题确实踩了不少细节坑——可选属性的组合、匹配优先级、权重排序,要是用嵌套判断确实会写得一团糟。我来分享一个Swift里简洁又易维护的实现思路,完美贴合你的需求:
第一步:明确基础定义
先把你提到的两个类补全(方便后续代码运行):
class OptionalObject { let prop1: String? let prop2: String? let prop3: String? let prop4: String? init(prop1: String?, prop2: String?, prop3: String?, prop4: String?) { self.prop1 = prop1 self.prop2 = prop2 self.prop3 = prop3 self.prop4 = prop4 } } class ConcreteObject { let arg1: String let arg2: String let arg3: String let arg4: String init(arg1: String, arg2: String, arg3: String, arg4: String) { self.arg1 = arg1 self.arg2 = arg2 self.arg3 = arg3 self.arg4 = arg4 } }
第二步:封装匹配得分计算
为OptionalObject扩展一个方法,计算它和ConcreteObject的匹配得分——我们用元组存储两个关键值:匹配属性的数量、匹配属性的权重总和。这样后续排序会非常直观:
extension OptionalObject { func matchScore(against concrete: ConcreteObject) -> (matchCount: Int, totalWeight: Int) { // 定义各属性权重:prop1最高,prop2最低 let propertyRules = [ (self.prop1, concrete.arg1, 4), // prop1权重4 (self.prop3, concrete.arg3, 3), // prop3权重3 (self.prop4, concrete.arg4, 2), // prop4权重2 (self.prop2, concrete.arg2, 1) // prop2权重1 ] // 用reduce遍历所有属性,累计匹配数和权重 return propertyRules.reduce((0, 0)) { result, rule in let (currentCount, currentWeight) = result let (optionalProp, concreteVal, weight) = rule // 只有当可选属性非nil且和对应值相等时,才累计得分 guard let prop = optionalProp, prop == concreteVal else { return result } return (currentCount + 1, currentWeight + weight) } } }
第三步:找到最优匹配对象
利用Swift的max(by:)方法,直接根据得分规则排序找到最优对象——不需要繁琐的filter嵌套,逻辑一目了然:
func findBestMatch(from optionalObjects: [OptionalObject], for concrete: ConcreteObject) -> OptionalObject? { return optionalObjects.max(by: { obj1, obj2 in let score1 = obj1.matchScore(against: concrete) let score2 = obj2.matchScore(against: concrete) // 排序规则:先比匹配数量(多的优先),数量相同比权重总和(高的优先) if score1.matchCount != score2.matchCount { return score1.matchCount < score2.matchCount } else { return score1.totalWeight < score2.totalWeight } }) }
验证你的示例场景
比如你提到的ConcreteObject(arg1: "DEF", arg2: "123", arg3: "Hello", arg4: "Goodbye"):
Obj7的prop1=DEF、prop2=123、prop4=Goodbye匹配,得分是(3, 4+1+2=7)Obj3的prop3=Hello、prop4=Goodbye匹配,得分是(2, 3+2=5)- 其他对象得分更低,所以
findBestMatch会直接返回Obj7,完全符合预期。
再比如两个都匹配2个属性的场景:
New1匹配prop2和prop4,得分(2, 1+2=3)New2匹配prop1和prop3,得分(2, 4+3=7)- 此时会选中
New2,符合权重优先的规则。
方案优势
- 代码简洁易维护:所有匹配逻辑封装在扩展里,后续增减属性只需要修改
propertyRules数组 - 逻辑直观:用元组存储得分,排序规则完全贴合你的需求,可读性拉满
- 性能高效:直接遍历一次数组找到最优解,不需要多次filter或嵌套判断
内容的提问来源于stack exchange,提问作者A O
相关产品推荐
相关产品推荐

