使用foreach和map

时间:2016-08-11 05:36:32

标签: scala

我是Scala的新手,我对功能如何拼接在一起以及它们的返回类型感到困惑。请考虑以下事项:

val nodes = List(0,1,2)               
val links = List(List(1, 2), List(1, 0), List(1,3))

每个节点都有一个双向链接,如元组对链接'中所述。我正在尝试构建一个地图,其中每个节点都指向它的邻居,例如

Map(0 -> List(1), 1 -> List(2, 0), 2 -> List(1) )

然而,我最初想的如何对此进行编码让我难以理解为什么它会返回一个空的' List [Any]'值。

nodes.foreach(z => (links.map { case List(a,b) => if(a == z) a else if (b == z) b }))

这样做的正确方法是什么?

3 个答案:

答案 0 :(得分:3)

或者,

scala> nodes.map(n => (n, links.flatMap {
     | case List(`n`, x) => Some(x)
     | case List(x, `n`) => Some(x)
     | case _ => None }))
res3: List[(Int, List[Int])] = List((0,List(1)), (1,List(2, 0, 3)), (2,List(1)))

如评论所述,

scala> .toMap
res4: scala.collection.immutable.Map[Int,List[Int]] = Map(0 -> List(1), 1 -> List(2, 0, 3), 2 -> List(1))

答案 1 :(得分:0)

您的代码中存在一些问题:

首先,foreach会返回Unit,您可以在Scala Doc

中看到

此外,您的情况并非完全正确 - 例如对于节点0和连接1<->0,您打算0,但实际上您想要返回1

正确的代码如下:

val nodes = List(0,1,2)               
val links = List(List(1, 2), List(1, 0), List(1,3))
val result = nodes.map(z => 
    (z, links.flatMap { 
                case List(a,b) => if(a == z && nodes.contains(b)) Some(b) else if (b == z && nodes.contains(a)) Some(a) else None 
              }
    )
).toMap
println(result)

请注意我在map列表中调用nodes的方式(而不是foreach) - 这样我就可以在最后调用toMap - 这是返回Map(最终想要实现的目标)。此外,我映射将每个节点ping到节点的Pair和其邻居列表

注2:我添加了一个条件,检查发现的邻居是否是节点集合的一部分(contains) - 这就是你的例子。如果您有不同的要求,只需将其删除

即可

会给:

Map(0 -> List(1), 1 -> List(2, 0), 2 -> List(1))

答案 2 :(得分:0)

我不确定您在代码示例中获得List[Any]的位置。

但是,foreach采用返回类型为Unit的函数作为参数,因此返回Unit。对于副作用,它基本上是每个循环的经典

地图&#39; List 集合的功能可以将List[A]变为List[B]。因此,如果您要在List[Int]函数中返回Intmap,那么两者的最小共同祖先类型{{1}所以结果是Any

但是,由于scala具有非常强大的集合API,因此有一个简单的解决方案。

明确地,您可以使用函数List[Any]

提供CanBuildFrom[List[Int], List[Int], Map[Int, Int]]来构建Map[Int, List[Int]]来自List[Int]映射

但是 scala提供了一种更简单的方法来实现它(看看breakOut)。

所以,如果我正确地解释了你的问题,你需要这样的东西:

Int => (Int, Int)