假设我想编写一个函数def pair(s:String):Option[(String, String)]
来将字符串转换为Scala中的键值对。该字符串应该看起来像"<key>:<value>"
。
您如何更正以下解决方案?
def pair(s:String) = { val a = s.split(":"); if (a.length == 2) Some((a(0).trim, a(1).trim)) else None }
答案 0 :(得分:8)
我个人觉得两种方法更好一点:
def pair(s: String) = s.split(":") match {
case Array(k, v) => Some(k.trim -> v.trim)
case _ => None
}
或使用Scala方便的正则表达式提取器:
val Pair = """\s*([^\s:]+)\s*:\s*([^\s:]+)\s*""".r
def pair(s: String) = s match {
case Pair(k, v) => Some(k -> v)
case _ => None
}
但是,你的也不是那么糟糕。
答案 1 :(得分:4)
我会删除分号并将其分为两行。否则它是一个完全精细的功能代码。
第二眼看模式匹配似乎更合适:
def pair(s:String) =
s.split(":") match {
case Array(a, b) => Some(a, b)
case _ => None
}
在这种情况下,模式匹配更适合的原因是您使用if-else
来模拟数据结构解构 - 确切的事情,模式匹配的用途。这会让您获得更低的抽象级别,更多的逻辑和更多的植入bug的机会。因此,您的实现依赖于a(0)
中的部分功能,这始终是一种沮丧的做法。
部分函数是一个未为其输入的整个域定义的函数。在您的情况下,这意味着在空数组上调用a(0)
将导致异常,但不会导致有意义的功能结果。在这个特定示例中,if
条件可以保护您免受该场景的影响,但是如果将此条件置于函数体之外,则在更复杂的情况下,使用部分函数会成为潜在的错误。这就是为什么不鼓励它作为一般做法。
但我也必须提一下,你不应该对if-else
构造一般不赞成。它是一个非常有效的功能表达,有其用途。只是在这个特定的例子中,这是一种次优的方法。