我是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 }))
这样做的正确方法是什么?
答案 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]
函数中返回Int
或map
,那么两者的最小共同祖先类型{{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)