我想了解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)
Tuple2
,但由于map2
是Map
而不是Tuple2
,所以零元素是什么?List
,即list1
时,我们总是“抓住list1
中的下一个元素”。什么是“map1
中的下一个元素?是另一对map1
吗?答案 0 :(得分:6)
在此上下文中,您可以将Map
视为元组列表。您可以创建如下列表:List(1 -> 2.0, 3 -> 4.0, 5 -> 6.2)
,并在其上调用foldLeft
(这或多或少与Map.foldLeft
完全相同)。如果您了解foldLeft
如何使用列表,那么现在您也知道它如何与地图一起使用:)
回答您的具体问题:
foldLeft
的第一个参数可以是任何类型。您也可以在第一个示例中传入map而不是int。它不必与您正在处理的集合的元素(尽管可能是)具有相同的类型,就像您在第一个示例中所拥有的那样,也不需要与集合本身的类型相同,就像您一样在最后一个例子中有它。
考虑这个例子:
List(1,2,3,4,5,6).foldLeft(Map.empty[String,Int]) { case(map,elem) =>
map + (elem.toString, elem)
}
这会产生与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
}
正如我在开头所解释的那样,这个上下文中的地图是一种列表(相反的序列)。就像"我们总是采用列表中的下一个元素"当我们处理列表时,我们将采用地图的" next元素"在这种情况下。你自己说,地图的元素是元组,所以下一个元素的类型是什么:
Map("one" -> 1, "two" -> 2, "three" -> 3)
.foldLeft("") {
case("", (key,value)) => key + "->" + value
case(s, (key,value)) => s + ", " + key + "->" + value
}