【问题标题】:Scala how to get the key of Map where value as ListScala如何获取Map的键,其中值为List
【发布时间】:2018-10-01 09:22:00
【问题描述】:

我有这样的地图:

val myMap = Map(
    testKey1 -> List(testValue1, testValue2, testValue3....), 
    testKey2 -> List(testValue4, testValue5, testValue6....),
    testKey3 -> List(testValue7, testValue8, testValue9....)
)

我想做一些list值的精确匹配,得到map对应的key。

例如:我想检查 'testValue9' 是否在此 Map 中,然后我会得到键 'testKey3'。

我认为它可以通过这种方式解决,但我无法遍历列表的值来检查该值是否存在。 或者有人可以给我一些提示。

myMap foreach {
          case (key, List(_)) => println( key )
          case _ =>    
        }

【问题讨论】:

  • 作为一般评论,对于此用例,Map 是一个相当糟糕的数据结构选择。

标签: scala


【解决方案1】:

如果您尝试在 Map 中查找单个值,您可以使用 find

  myMap.find(_._2.contains(value)).map(_._1)

如果找到值,则返回Some(key),否则返回None

如果您认为可能有多个匹配值,可以将find替换为filter

  myMap.filter(_._2.contains(value)).map(_._1)

或使用collect

  myMap.collect{ case (k, v) if v.contains(value) =>  k }

在这两种情况下,这将返回所有匹配键的列表,并取决于Map 的实现方式。

请注意,filter 选项可以使用 for 表达式来表达,其作用完全相同:

  for { (k,v) <- myMap if v.contains(value) } yield k

虽然collect 的性能可能最好,但在大多数情况下,这只是一个风格问题,即哪个更好。

更新

Raman Mishra 有用地指出过滤器版本可以简化为

myMap.filter(_._2.contains(value)).keys

这会返回Set 而不是List,后者更合适,因为顺序并不重要。

【讨论】:

  • map(_._1) 在过滤器中不是必需的,我们可以使用 .keys
  • 我喜欢该解决方案提供了一个示例,该示例适用于 Map 可能具有不同的长列表的情况。
【解决方案2】:

我想你想这样做:

假设 Key 是 String 并且 value 是 List[String]

val keyContainsValue: immutable.Iterable[String] = myMap map {
    case (key, value) => if (value.contains(testValue9)) key else ""
  }

你可以使用空字符串作为默认值,这样你就可以得到返回类型为iterable[String]。

由于我不知道您的键和值的类型,您也可以使用选项。为此目的。

val keyContainsValue: immutable.Iterable[Option[String]] = myMap map {
        case (key, value) => if (value.contains(testValue9)) Some(key) else None
      }
println(keyContainsValue.flatten) //you will get the list of keys which contains the value specified.

【讨论】:

  • 您的case _ 是不必要的,因为第一个case 将始终匹配。并且使用collect 将避免需要创建一个默认值然后再次删除它。
【解决方案3】:
val searchValue = "testValue9"

myMap.collect{ case (key, values) if values.contains(searchValue) => key }

【讨论】:

    【解决方案4】:

    你可以做类似的事情

    val getKeys = (k: String) => for (m<- myMap.keys;
                                     v<- myMap(m);
                                     if v==k) yield m
    

    【讨论】:

    • 为什么要遍历键然后查找值?最好只遍历键/值对。
    • 因为该值是一个列表,我想对其进行迭代。确实,使用 contains 更有效,因为它会短路
    猜你喜欢
    • 1970-01-01
    • 2021-07-07
    • 2022-11-18
    • 2021-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多