我正在学习scala,并对我得到的错误感到困惑。我正在尝试使用不同的容器,目前我有一个地图列表,每个地图共享相同的键。我正在尝试使用for循环遍历列表并将对应于键“startlocation”的值放入Node类型的数组中(我制作的类),但我似乎无法正确使用语法。当我试图从列表中的当前地图获取该键的值时,它告诉我我的密钥是一个不正确的参数。
此代码有什么问题,我该怎么做才能修复它?
class Node{
var visited = false;
var mDistance = 10000;
var prevLoc = " ";
}
object test{
def main(args: Array[String]){
var i = 0;
var l = List(Map("startlocation" -> "Kruthika's abode", "endlocation" -> "Mark's crib", "distance" -> 10),
Map("startlocation" -> "Mark's Crib", "endlocation" -> "Kirk's Farm", "distance" -> 9));
var b = new Array[Node](l.size);
var index = 0;
for(i <- l){
b(index).prevLoc = i("startlocation"); // This is the line where the error occurs
index++;
}
}
}
特定错误:类型不匹配;发现:任何必需:字符串
此错误突出显示了我在上面评论的行中的“startlocation”。
答案 0 :(得分:5)
首先,地图定义存在很大问题。由于您使用Int
和String
作为值类型,因此结果类型被推断为这些值的最可能的具体公共超类型,Any
,因为String
和{{1非常不同。
正确的做法?看起来您的地图有意预设了一组密钥,这些密钥在scala中通过Int
es甚至更好class
更好地实现,因此您可以定义case class
类附近
Node
以后
case class Route(startLocation: String, endLocation: String, distance: Int)
甚至
val l = List(
Route( startLocation = "Kruthika's abode", endLocation = "Mark's crib", distance = 10),
Route( startLocation = "Mark's Crib", endLocation = "Kirk's Farm", distance = 9))
最后
val l = List(
Route( "Kruthika's abode", "Mark's crib", 10),
Route( "Mark's Crib", "Kirk's Farm", 9))
scala中没有postfix b(index).prevLoc = i.startLocation // This is the line where the error occurs
运算符,因此++
至少应为index++
index += 1
iables 您经常可以避免var
定义。
例如var
过多,因为它甚至没有在您的代码中使用
因为在var i = 0;
中创建了新的for(i <- l)
定义,该定义仅在循环内有效
此外,您可以避免i
的定义,您可以使用索引迭代收集
var index
同样,你经常可以避免for((i, index) <- l.zipWithIndex)
中的var
iables,使类不可变。您可以在每次需要时创建新实例(可能是class
exisitng)而不是变异。
这对您的代码至关重要,因为.copy()
肯定会抛出b(index).prevLoc
,因为在您的数组中没有创建NullPointerException
的实例。
想象一下你定义了
Node
使用就是
case class Node(visited: Boolean = false, mDistance: Int = 10000, prevLoc: String = " ")
Node(prevLoc = i.startLocation)
(列出序列≺monad)理解最后,您的for
现在可以翻译为b
不可变val
,因为List
是从现有的for
创建新集合的表达式。有了这样的声明,您甚至不需要知道当前索引,因此您可以删除建议的yield
部分
.zipWithIndex
最后 - 大多数时候你几乎可以在行尾避免;
总结一下,整个代码可以翻译成
;
您可以将case class Node(visited: Boolean = false, mDistance: Int = 10000, prevLoc: String = " ")
case class Route(startLocation: String, endLocation: String, distance: Int)
object test{
def main(args: Array[String]){
val l = List(
Route( "Kruthika's abode", "Mark's crib", 10),
Route( "Mark's Crib", "Kirk's Farm", 9))
val b = for(i <- l) yield Node(prevLoc = i.startLocation)
}
}
添加到println(b)
方法的末尾,以查看如何打印main
和List
答案 1 :(得分:2)
这是因为你在地图中混合了String和Int类型。 'prevLoc'似乎是一个String,但你的地图包含Any(scala编译器推断这种类型,因为你没有指定任何类型)。
我建议您将地图显式设为Map[String, String]
。在这种情况下,您的程序将无法编译(您有一些整数作为地图值,您可以执行"distance" -> 10.toString
之类的操作。)
P.S。尽量避免使用var
:可以使用不可变变量(val
s)和map
,filter
,{{1}等函数编写没有它的Scala代码以功能的方式。
答案 2 :(得分:1)
你可以这样试试,
val l = List(Map("startlocation" -> "Kruthika's abode", "endlocation" -> "Mark's crib", "distance" -> 10),
Map("startlocation" -> "Mark's Crib", "endlocation" -> "Kirk's Farm", "distance" -> 9));
case class Node(visited:Boolean = false, mDistance:Int = 10000, prevLoc:String)
l.map(x=>Node(prevLoc = x("startlocation").asInstanceOf[String]))