【问题标题】:Scala: How to return the key that contains an item in their value where value is a Set?Scala:如何返回值中包含一个项的键,其中值是一个集合?
【发布时间】:2016-11-11 15:29:23
【问题描述】:

我有一个Map[Int, Set[Int]],并且给定一个项目,我想返回索引到该项目所在的集合的键。例如,如果我有一个Map(1 -> Set("a"), 2 -> Set("b"), 3 -> Set("c","z"))。假设项目是"z" 我想返回3 因为3 是索引到包含3 的集合的键。 这是我目前拥有的,但我似乎找不到获取密钥的好方法。我只能得到价值,Set[Int]。假设该项目将仅在一个可能的集合中。

def find(djs: Map[Int, Set[Int]], item: Int) :Int = {
for ((key, set) <- djs) {
  if (set.contains(item)) {
    key
  } 
}

【问题讨论】:

  • 如果item在多个key下,你想返回什么?
  • 你的意思是Set("c", "z"),还是真的是1个字符串的集合?
  • @jwvh 假设该项目将仅在一个可能的集合中,否则没有。我添加到问题中。
  • @soote 我编辑了问题,我的意思是 Set("c", "z")。
  • 似乎您以错误的方式使用地图...为什么不保留一个地图(另一个?)将一个元素映射到它所在的集合?或者可能是Map[Int, (Int, Set[Int]),其中第二个 Int 是您正在寻找的关键..

标签: scala dictionary set


【解决方案1】:

collectFirst 就是为此而生的:

val m = Map(1 -> Set("a"), 2 -> Set("b"), 3 -> Set("c","z"))

m.collectFirst{case (k,v) if v.contains("z") => k}
//> res0: Option[Int] = Some(3)

我总是忘记Set 本身可以用作函数(即applycontains 相同)

m.collectFirst{case (k,v) if v("z") => k}
//> res0: Option[Int] = Some(3)

【讨论】:

  • 这很好!在效率方面,这是最好的吗?
  • 它遍历列表一次,因此它比查找/映射更有效,并且可能与平面图大致相同。但除非你真的需要微优化,否则我认为清晰度更重要
  • 而“效率”取决于。如果您要进行大量此类查找,则构建一个反向映射,
【解决方案2】:

如果您需要返回一个或None,那么Option[] 将是您的最佳选择。如果需要返回一个、多个或无,则返回 List[] 可能是合适的。

val m = Map(1 -> Set("a"), 2 -> Set("b"), 3 -> Set("c","z"))

m.flatMap{ case (k,vs) => if (vs.contains("z")) Seq(k) else Seq() }  // List(3)
m.flatMap{ case (k,vs) => if (vs.contains("w")) Seq(k) else Seq() }  // List()

【讨论】:

  • 过滤器是这个任务的更具描述性的霍夫,不是吗? m.filter(_._2.contains("z")).map(_._1)
【解决方案3】:

find 运算符在这里可以很好地工作:

def find[A, B](m: Map[A, Set[B]], item: B): Option[A] = 
    m.find { case (key, set) => set.contains(item) }
     .map  { case (key, set) => key }

【讨论】:

  • .map(_._1 到底是干什么用的?
  • 获取元组中的第一个值。所以在这种情况下,它只返回密钥。
猜你喜欢
  • 1970-01-01
  • 2021-12-24
  • 2021-06-10
  • 2019-06-15
  • 1970-01-01
  • 2013-02-18
  • 1970-01-01
  • 2017-09-18
  • 1970-01-01
相关资源
最近更新 更多