优化MQTT主题过滤Scala函数:寻求更简洁实现方案
简化MQTT主题匹配的Scala函数
我写了一个MQTT主题匹配的逻辑函数,所有测试均已通过,但这个Scala函数过于冗长繁琐,我确信可以大幅简化。
相关规则说明:
self是我们订阅的主题,可包含零个或多个通配符incoming是接收消息的主题,需与self完全匹配或符合通配符规则
原函数代码
def filterTopic(incoming: String, self: String): Boolean = { if (incoming == self || self == "#") { true } else if (self.startsWith("#") || (self.contains("#") && !self.endsWith("#")) || self.endsWith("+")) { false } else { var valid = true val selfSplit = self.split('/') var j = 0 for (i <- selfSplit.indices) { if (selfSplit(i) != "+" && selfSplit(i) != "#" && selfSplit(i) != incoming.split('/')(i)) { valid = false } j += 1 } if (j < selfSplit.length && selfSplit(j) == "#") { j += 1 } j == selfSplit.length && valid } }
简化后的函数
利用Scala的函数式特性,我们可以消除可变变量,让逻辑更清晰简洁:
def filterTopic(incoming: String, self: String): Boolean = { // 完全匹配或订阅所有主题的情况 if (incoming == self || self == "#") true // 无效订阅主题格式:#不在末尾、+在末尾、#开头但非单独# else if (self.contains("#") && !self.endsWith("#") || self.endsWith("+")) false else { val incomingParts = incoming.split('/').toList val selfParts = self.split('/').toList // 拆分出#之前的所有需要匹配的层级 val (matchingSegments, _) = selfParts.span(_ != "#") // 逐个层级匹配:要么是+通配符,要么与incoming对应层级完全一致 val segmentsMatch = matchingSegments.zipAll(incomingParts, "", "").forall { case (subSeg, incomingSeg) => subSeg == "+" || subSeg == incomingSeg } // 确保需要匹配的层级数量不超过incoming主题的层级数 segmentsMatch && matchingSegments.length <= incomingParts.length } }
简化说明
- 保留原函数核心判断逻辑,用更直观的条件表达
- 用
span拆分订阅主题中#前后的部分,替代手动循环计数 - 用
zipAll处理两个主题层级数量不一致的情况,配合forall实现批量匹配,消除原有的for循环和可变变量 - 整体逻辑线性清晰,代码简洁易读,同时保持原有匹配准确性
内容的提问来源于stack exchange,提问作者GSerum_
相关产品推荐
相关产品推荐

