【发布时间】:2015-08-27 22:18:55
【问题描述】:
我有一个summaryPool 可变映射,它将一个字符串映射到一个摘要对象。
函数namesToSummary有两个参数,第一个是一系列名称(在Iterable[String]中),第二个是summaryPool。它的作用是返回一系列对应名称的摘要。
这有点复杂,因为应该使用正则表达式检查名称以提取曾经是 summaryPool 的键的信息。
例如,“summary1b”应该检查得到“summary1”和“b”; “summary1”是池的关键。在某些情况下,可能没有附加“b”。
我的实现使用isSummaryPool 函数来过滤掉格式错误的名称,或者不在池中的名称。然后,我使用 map 来获取池中 Summary 对象的副本。
import scala.collection.mutable.{Map => mm}
def namesToSummaries(names: Iterable[String], summaryPool: mm[String, Summary]) = {
val namePattern = """([a-zA-Z]+\d+)([a-z])?""".r
def inSummaryPool(name: String) = {
name match {
case namePattern(summaryName, summaryType) => {
if (summaryPool.contains(summaryName)) true
else false
}
case _ => false
}
}
names filter inSummaryPool map { name =>
name match {
case namePattern(summaryName, summaryType) => {
var sType = summaryType
if (sType == null || !(sType == "b" || sType == "l")) sType = "b"
summaryPool.get(summaryName).get.copy(sType)
}
}
}
}
它工作正常,但我不喜欢它的实现,因为它会检查正则表达式匹配两次。
我想我可以将过滤器/地图集成到带有警卫的地图中。为了做到这一点,我想我可能需要实现类似这样:
import scala.collection.mutable.{Map => mm}
def namesToSummaries(names: Iterable[String], summaryPool: mm[String, Summary]) = {
val namePattern = """([a-zA-Z]+\d+)([a-z])?""".r
names map { name =>
name match {
case namePattern(summaryName, summaryType) => {
if (summaryPool.contains(summaryName)) {
var sType = summaryType
if (sType == null || !(sType == "b" || sType == "l")) sType = "b"
summaryPool.get(summaryName).get.copy(sType)
}
else
???
}
case _ => ???
}
}
}
我不确定应该在 ???教 Scala 忽略这些情况。
可能的解决方案是什么?
编辑1
我可以考虑在必要时制作一个 ListBuffer 对象来添加 Summary 对象。 但是,我不确定模式不匹配的情况。
val list: ListBuffer
names foreach { name =>
name match {
case namePattern(summaryName, summaryType) => {
if (summaryPool.contains(summaryName)) {
var sType = summaryType
if (sType == null || !(sType == "b" || sType == "l")) sType = "b"
list += summaryPool.get(summaryName).get.copy(sType)
}
}
case _ => ???
}
}
}
EDIT2
从 Shadowlands 的回答来看,没有返回的 flatMap 可以正常工作。
def namesToSummaries(names: Iterable[String], summaryPool: mm[String, Summary]) = {
val namePattern = """([a-zA-Z]+\d+)([a-z])?""".r
names flatMap { name =>
name match {
case namePattern(summaryName, summaryType) => {
if (summaryPool.contains(summaryName)) {
var sType = summaryType
if (sType == null || !(sType == "b" || sType == "l")) sType = "b"
Some(summaryPool.get(summaryName).get.copy())
}
else None
}
case _ => None
}
}
}
编辑3
根据 Jilen 的提示,collect 似乎是减少更多代码行数的好方法。
def namesToSummaries(names: Iterable[String], summaryPool: mm[String, Summary]) = {
val namePattern = """([a-zA-Z]+\d+)([a-z])?""".r
names collect { name =>
name match {
case namePattern(summaryName, summaryType) if (summaryPool.contains(summaryName)) => {
var sType = summaryType
if (sType == null || !(sType == "b" || sType == "l")) sType = "b"
summaryPool.get(summaryName).get.copy()
}
}
}
}
但是,IntelliJ 14 中的此代码显示误报错误:这是一个错误报告 (https://youtrack.jetbrains.com/issue/SCL-9094#)。
【问题讨论】:
-
我认为你应该使用
collect,它可以简化为this
标签: regex scala dictionary filter