【问题标题】:filter/map structure to map/guard structure in Scala过滤器/映射结构映射/保护结构在Scala
【发布时间】: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


【解决方案1】:

不要在名称上调用map,而是尝试使用flatMap。将您的成功案例包装在Some(...) 中,??? 变为None。 flatMap 的“扁平化”部分会将“映射”的Iterable[Option[String]] 减少回Iterable[String],放弃所有None 的情况。

编辑:我没有足够仔细地研究您的代码 - 在“成功”的情况下,您似乎在做纯粹的副作用(即更新可变映射),而不是返回任何类型的结果。

此时您可以改为返回 (summaryName, summaryType) 元组(包装在 Some 中)并将副作用代码应用于生成的 flatMap 的内容(可能我更喜欢功能性更强的样式) ,或者干脆回到使用 map 并只写 _(这里的意思是:'什么都不做 - 忽略任何结果')而不是 ???

【讨论】:

    猜你喜欢
    • 2015-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-20
    • 1970-01-01
    • 2014-10-03
    • 1970-01-01
    相关资源
    最近更新 更多