scala - Scala:从元组列表构建Map,但是如果存在矛盾的条目则失败

标签 scala collections

我认为这可能是常见的操作。因此,也许它在API内,但我找不到它。如果没有的话,我也对有效的功能/简单解决方案感兴趣。

给定一个元组("a" -> 1, "b" ->2, "c" -> 3)的序列,我想将其转换为 map 。使用TraversableOnce.toMap很容易。但是,如果结果映射“将包含矛盾”,即为同一键分配不同的值,我想使这种构造失败。就像序列("a" -> 1, "a" -> 2)一样。但应允许重复。

目前,我有这个(非常必要的)代码:

def buildMap[A,B](in: TraversableOnce[(A,B)]): Option[Map[A,B]] = {
  val map = new HashMap[A,B]
  val it = in.toIterator
  var fail = false
  while(it.hasNext){
    val next = it.next()
    val old = map.put(next._1, next._2)
    fail = old.isDefined && old.get != next._2
  }

  if(fail) None else Some(map.toMap)
}

附带问题

最后的toMap是否真的必要?省略时会出现类型错误,但我认为它应该起作用。 toMap的实现构造了一个我想避免的新 map 。

最佳答案

Seq[A]一样,最佳解决方案的性能取决于具体的收集类型。
一个通用但不是很有效的解决方案是将折叠到Option[Map[A,B]]上:

def optMap[A,B](in: Iterable[(A,B)]): Option[Map[A,B]] = 
  in.iterator.foldLeft(Option(Map[A,B]())) {
    case (Some(m),e @ (k,v)) if m.getOrElse(k, v) == v => Some(m + e)
    case _ => None
  }

如果您限制使用List[A,B],则优化版本为:
@tailrec
def rmap[A,B](in: List[(A,B)], out: Map[A,B] = Map[A,B]()): Option[Map[A,B]] = in match {
  case (e @ (k,v)) :: tail if out.getOrElse(k,v) == v =>
    rmap(tail, out + e)
  case Nil =>
    Some(out)
  case _ => None
}

另外,使用可变映射的惯用性较低的版本可以这样实现:
def mmap[A,B](in: Iterable[(A,B)]): Option[Map[A,B]] = {
  val dest = collection.mutable.Map[A,B]()

  for (e @ (k,v) <- in) {
    if (dest.getOrElse(k, v) != v) return None
    dest += e
  }

  Some(dest.toMap)
}

关于scala - Scala:从元组列表构建Map,但是如果存在矛盾的条目则失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5966535/

相关文章:

java - 是否有类似 "Java shared libraries"的内容可以最大限度地减少已部署应用程序的磁盘占用空间?

python - 为什么在 PyMongo 中处理大型 MongoDB 集合时会丢失数据?我该怎么办?

Java 集合脑筋急转弯

java - 快速 Java 垃圾收集问题

scala - 如何将特征混合到实例中?

scala - 多次混合相同特征的规则

具有多个参数的 Scala Elasticsearch 查询

scala - 为什么这个Iterable在映射后会产生一个Set?

java - EasyMock 期望使用 Collection 类型的参数调用方法

java - 你怎么改Play 2.1!框架 session cookie 名称