【问题标题】:Pattern matching against Scala Map entries针对 Scala Map 条目的模式匹配
【发布时间】:2013-09-06 08:22:47
【问题描述】:

是否有任何 Scala 技巧来启用对映射键的模式匹配?换句话说,我希望有一个提取器,它在 Map 实例旁边还接受一个键值,这意味着我希望此模式仅在可匹配值是 Map 的实例并且存在具有给定键的条目时才匹配在其中,并且该条目的值受递归模式匹配的影响。

类似这样的:

myMap match {
    case MyMap("a")(a) => // do smth with value a
    case MyMap("b")(MyMap("c")(c)) => // do smth with value c
}

更新:

我找到了一些更接近目标的方法,但它仍然不完美,因为它暗示了合成键值持有者的定义:

case class MapKey[K](key: K) {
  def unapply(o: Any) = o match {
    case m: Map[K, _] ⇒ m.get(key)
    case _ ⇒ None
  }
}

val m1 = Map("a" → "aa", "b" → Map("c" → "cc"))
val m2 = Map("a" → "aa", "d" → "dd")

val b = MapKey("b")
val c = MapKey("c")
val d = MapKey("d")

for (m ← List(m1, m2)) m match {
  case b(c(x)) ⇒ println(s"b > c: $x")
  case d(x) ⇒ println(s"d: $x")
}

类似问题:Can extractors be customized with parameters in the body of a case statement (or anywhere else that an extractor would be used)?

功能请求:SI-5435

【问题讨论】:

  • 您确定还要匹配myMap 是否为地图吗?还能是什么?
  • 您希望匹配的第二个案例是什么?如果匹配,myMap 会是什么样子?
  • 这是一个简化的例子。实际上,我正在开发一个 Scala 库,用于对从 NSObject 派生的 Apple Cocoa 类型进行操作。特别是,任务是解析 iOS Plist 文件,该文件非常复杂,有多种替代方法来描述同一事物。
  • 我最初的解决方案是基于类似 map 的操作,按键返回 Option,但是源代码被大量链式 case _ => None 污染,所以我决定开发一个 helper,链式为 PartialFunction 提供 andThen和提升,但算法仍然看起来很丑陋。然后我问自己是否可以对模式匹配做同样的事情。
  • 如果您说明要实现的功能的签名,这将有所帮助。

标签: scala pattern-matching extractor


【解决方案1】:

也许您正在寻找您并不真正需要的解决方案?无法想象这里的提取器。如果要匹配键值对,可以使用 PF:

val map = Map[String, String]("a" -> "b")

def matchTuple[A,B,C](map: Map[A,B])(pf: PartialFunction[(A,B), C]) = 
  map.collectFirst(pf)

matchTuple(map) {
  case ("a", b) => println("value for a is " + b)
}

返回类型是 Option[Unit] 因为我们使用 collectFirst 和 println

【讨论】:

  • PartialFunction 与 andThen 链接并通过 .lift 进行选项化是我迄今为止实现此算法的方式。但是,我很好奇是否有可能以更简洁的方式进行。
  • 我认为这是一个数学错误的任务。使用 match 查找无序映射的元素会产生不可预测的结果
猜你喜欢
  • 1970-01-01
  • 2014-09-30
  • 2011-11-27
  • 2014-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-26
  • 2018-09-23
相关资源
最近更新 更多