Algorithm 如何根据模式匹配将一个贴图中的值替换为另一个贴图中的值?

Algorithm 如何根据模式匹配将一个贴图中的值替换为另一个贴图中的值?,algorithm,scala,functional-programming,maps,match,Algorithm,Scala,Functional Programming,Maps,Match,我有一个有几个键值对的映射,我想要一种方法来遍历这些键值对,并尝试将这些键值与另一个映射的值相匹配。如果存在匹配项,则值将相互替换。换句话说,如果存在匹配,则第二个映射的值将替换第一个映射的值。如果没有匹配项,则不包括在结果中 我已经尝试过使用scala.map函数来计算逻辑,但是我对scala不太熟悉,不能完全理解它 例如,我有以下两个scala映射[String,String]: val lookupMap = Map("aaa" -> "apple", "bbb" -> "or

我有一个有几个键值对的映射,我想要一种方法来遍历这些键值对,并尝试将这些键值与另一个映射的值相匹配。如果存在匹配项,则值将相互替换。换句话说,如果存在匹配,则第二个映射的值将替换第一个映射的值。如果没有匹配项,则不包括在结果中

我已经尝试过使用scala.map函数来计算逻辑,但是我对scala不太熟悉,不能完全理解它

例如,我有以下两个scala映射[String,String]:

val lookupMap = Map("aaa" -> "apple", "bbb" -> "orange", "ccc" -> "banana")

val entriesMap = Map("foo" -> "ccc", "bar"-> "aaa", "baz" -> "zzz") 

我想通过某种方式获得以下结果:

val result = Map("foo" -> "banana", "bar" -> "apple")

注意:“baz”未包括在内,因为它与查找映射中的任何内容都不匹配

A
for
理解可以解决这个问题

val result = for {
               (k,ev) <- entriesMap
               lv     <- lookupMap.get(ev)
             } yield (k,lv)
//result: Map[String,String] = Map(foo -> banana, bar -> apple)
val result=for{
(k,ev)苹果(apple)

让我们用更简单的步骤来解决问题

  • 过滤掉
    entriesMap
    上的所有对,这些对的值在
    lookupMap
    中不作为键存在
  • 映射其余对以更改与原始值关联的
    lookupMap
    上的值的值
  • 因此,您可以编写以下内容:

    val result =
      entriesMap
        .filter { case (_, value) => lookupMap.contains(key = value) }
        .map { case (key, value) => key -> lookupMap(value) }
    
    但是,每次您想
    过滤
    ,然后
    映射
    ,都可以使用
    收集
    (这将完成相同的工作,但只需一次迭代)。
    因此,您可以这样写:

    val result = entriesMap.collect {
      case (key, value) if lookupMap.contains(key = value) => key -> lookupMap(value)
    }
    
    现在,上述代码的一个“问题”是,它在映射上使用了不安全的
    apply
    ,如果它们的键不存在,就会抛出异常。 通常,应该使用
    get
    方法,该方法将返回包装在选项上的值,如果键不存在,该选项将是
    None

    在这种情况下,访问不是不安全的,因为我们正在检查之前是否存在密钥。
    无论如何,人们可以重新思考该计划:

  • 通过尝试在
    lookupMap
    上获取相关值,映射
    entriesMap
    的值
  • 筛选出其值现在为
    None
    的对,然后展开
    Somes
  • 代码如下:

    val result =
      entriesMap
        .view // Only if you are in 2.13
        .mapValues(value => lookupMap.get(key = value))
        .collect { case (key, Some(value)) => key -> value }
        .toMap // This is necessary because mapValues returns a view, which is a lazy collection.
               // Other option would have been to use just map instead of mapValues.
    
    最后,可以使用来理解,而不是直接使用高阶函数
    因此,该代码(与jwvh的答案几乎相同):

    val结果=
    为了{
    
    (关键、价值)@LuisMiguelMejíaSuárez您给出的第一个选项正是我想要的!您能用简单的英语解释一下您的想法吗?我正在尝试学习scala语法和函数式思维方式。另外,这个选项和第二个选项有什么区别?我注意到它返回了一个视图,但我不熟悉视图。这是代码吗afe?我这样问是因为下面的线程中有人提出了一个我没有考虑太多的问题。如果一个键不存在怎么办?这在任何情况下都会引发异常吗?或者它本身与一些或没有关系?@jjaguirre394;是的,它是安全的。你可以自己看到它会逐步通过
    entriesMap
    ,包括如果值存在(即
    某些(“…”)
    ),它将在
    查找映射上调用
    .get()
    ,该映射将返回一个
    选项[String]
    然后它被展开并分配给变量
    lv
    。如果不是这样,那么理解的
    就直接进入迭代。需求发生了变化,看起来现在我必须查找类型Map[String,Map[String,String]]。我提出的函数看起来像
    val res=for{(k,ev)@jjaguirre394;您的评论中没有足够的信息来提供一个自信的答案。您可能想提交一个包含足够细节的新问题,包括示例输入和预期输出。在此之前,我只能说
    lookupMap.get(k).get(ev)
    不起作用,因为
    lookupMap.get(k)
    返回一个
    选项
    ,而
    选项
    类型没有
    .get(key)
    方法。
    val result =
      for {
        (key, value) <- entriesMap // For each key-value pair in entriesMap...
        newValue <- lookupMap.get(key = value) // And for each newValue associated with each original value...
      } yield key -> newValue // Yield the key-newValue pair.