了解foldLeft with Map而不是List

时间:2016-05-06 10:34:19

标签: scala dictionary language-concepts foldleft

我想了解foldLeft对地图的作用。如果我有一个List并使用零元素和函数调用foldLeft,我确实理解它是如何工作的:

val list1 = List(1,2,3)
list1.foldLeft(0)((a,b) => a + b)

我使用0的第一个元素添加零元素list1,然后添加list1的第二个元素,依此类推。因此输出成为新输入,第一个输入是零元素。

现在我得到了代码

val map1 = Map(1 -> 2.0, 3 -> 4.0, 5 -> 6.2) withDefaultValue 0.0
val map2 = Map(0 -> 3.0, 3 -> 7.0) withDefaultValue 0.0
def myfct(terms: Map[Int, Double], term: (Int, Double)): Map[Int, Double] = ???

map1.foldLeft(map2)(myfct)
  1. 所以我的第一个元素是Tuple2,但由于map2Map而不是Tuple2,所以零元素是什么?
  2. 当我们有一个List,即list1时,我们总是“抓住list1中的下一个元素”。什么是“map1中的下一个元素?是另一对map1吗?

1 个答案:

答案 0 :(得分:6)

在此上下文中,您可以将Map视为元组列表。您可以创建如下列表:List(1 -> 2.0, 3 -> 4.0, 5 -> 6.2),并在其上调用foldLeft(这或多或少与Map.foldLeft完全相同)。如果您了解foldLeft如何使用列表,那么现在您也知道它如何与地图一起使用:) 回答您的具体问题:

  1. foldLeft的第一个参数可以是任何类型。您也可以在第一个示例中传入map而不是int。它不必与您正在处理的集合的元素(尽管可能是)具有相同的类型,就像您在第一个示例中所拥有的那样,也不需要与集合本身的类型相同,就像您一样在最后一个例子中有它。 考虑这个例子:

    List(1,2,3,4,5,6).foldLeft(Map.empty[String,Int]) { case(map,elem) => 
      map + (elem.toString, elem) 
    }
    
  2. 这会产生与list.map { x => x.toString -> x }.toMap相同的结果。如您所见,此处的第一个参数是Map,既不是List也不是Int

    传递给foldLeft的类型也是它返回的类型,以及传递的函数返回的类型。它不是"元素零"。 foldLeft会将该参数与列表的第一个元素一起传递给reducer函数。您的函数将组合这两个元素,并生成与第一个参数相同类型的新值。该值再次传入,第二个元素......等。 也许,检查foldLeft的签名会有所帮助:

       foldLeft[B](z: B)(op: (B, A) ⇒ B): B
    

    此处A是您的收藏元素的类型,B可以是任何内容,唯一的要求是它出现的四个地方具有相同的类型。

    这是另一个例子,它(几乎)等同于list.mkString(",")

       List(1,2,3,4,5,6).foldLeft("") { 
         case("", i) => i.toString
         case(s,i) => s + "," + i
       }
    
    1. 正如我在开头所解释的那样,这个上下文中的地图是一种列表(相反的序列)。就像"我们总是采用列表中的下一个元素"当我们处理列表时,我们将采用地图的" next元素"在这种情况下。你自己说,地图的元素是元组,所以下一个元素的类型是什么:

      Map("one" -> 1, "two" -> 2, "three" -> 3)
       .foldLeft("") { 
         case("", (key,value)) => key + "->" + value
         case(s, (key,value)) => s + ", " + key + "->" + value
       }