Scala Newb问题-关于范围和变量
我正在解析XML,并不断发现自己在编写代码,如:Scala Newb问题-关于范围和变量,scala,scoping,Scala,Scoping,我正在解析XML,并不断发现自己在编写代码,如: val xml = <outertag> <dog>val1</dog> <cat>val2</cat> </outertag> var cat = "" var dog = "" for (inner <- xml \ "_") { inner match { case <dog>{ dg @ _* }</dog> =>
val xml = <outertag>
<dog>val1</dog>
<cat>val2</cat>
</outertag>
var cat = ""
var dog = ""
for (inner <- xml \ "_") {
inner match {
case <dog>{ dg @ _* }</dog> => dog = dg(0).toString()
case <cat>{ ct @ _* }</cat> => cat = ct(0).toString()
}
}
/* do something with dog and cat */
val xml=
瓦尔1
瓦尔2
var cat=“”
var dog=“”
对于(内部狗=dg(0).toString()
case{ct@*}=>cat=ct(0).toString()
}
}
/*对狗和猫做点什么*/
这让我很恼火,因为我应该能够将cat和dog声明为val(不可变),因为我只需要设置它们一次,但我必须使它们可变。除此之外,似乎在scala中必须有更好的方法来实现这一点。有什么想法吗?考虑将XML检查和模式匹配封装在一个函数中,该函数将您需要的多个值作为元组返回(
Tuple2[String,String]
).但是停下来考虑一下:看起来有可能不匹配任何dog
和cat
元素,这将使一个或两个元组组件返回null。也许您可以返回选项[String]
的元组,或者在其中一个元素模式绑定失败时抛出
在任何情况下,通常都可以通过将组成语句包装到函数中以生成表达式来解决这些初始化问题。一旦有了表达式,就可以使用其求值结果初始化常量。考虑将XML检查和模式匹配包装到返回t的函数中您需要多个值作为一个元组(
Tuple2[String,String]
)。但是停下来考虑一下:看起来有可能不匹配任何dog
和cat
元素,这将使您为一个或两个元组组件返回null。也许您可以返回Option[String]的元组
,如果其中一个元素模式绑定失败,则抛出
在任何情况下,通常都可以通过将组成语句封装到函数中以生成表达式来解决这些初始化问题。一旦有了表达式,就可以使用其求值结果初始化常量。这里有两个(现在将其设为三个)可能的解决方案。第一种方法非常快速而且不干净。您可以在Scala解释器中运行整个部分
val xmlData = <outertag>
<dog>val1</dog>
<cat>val2</cat>
</outertag>
// A very simple way to do this mapping.
def simpleGetNodeValue(x:scala.xml.NodeSeq, tag:String) = (x \\ tag).text
val cat = simpleGetNodeValue(xmlData, "cat")
val dog = simpleGetNodeValue(xmlData, "dog")
cat1
将为“val2”;dog1
将为“val1”;goat
将为“未找到山羊”
更新:这里有一个更方便的方法获取标记名列表,并将其匹配项作为映射返回[String,String]
// Searches for all tags in the List and returns a Map[String, String].
def getNodeValues(x:scala.xml.NodeSeq, tags:List[String]) = {
tags.foldLeft(Map[String, String]()) { (a, b) => a(b) = simpleGetNodeValue(x, b)}
}
val tagsToMatch = List("dog", "cat")
val matchedValues = getNodeValues(xmlData, tagsToMatch)
如果运行该命令,匹配的值
将是映射(dog->val1,cat->val2)
希望有帮助
更新2:根据Daniel的建议,我正在使用双反斜杠操作符,它将下降到子元素中,随着XML数据集的发展,这可能会更好。这里有两个(现在是三个)可能的解决方案。第一个解决方案非常快速且肮脏。您可以在Scala解释器中运行整个部分
val xmlData = <outertag>
<dog>val1</dog>
<cat>val2</cat>
</outertag>
// A very simple way to do this mapping.
def simpleGetNodeValue(x:scala.xml.NodeSeq, tag:String) = (x \\ tag).text
val cat = simpleGetNodeValue(xmlData, "cat")
val dog = simpleGetNodeValue(xmlData, "dog")
scala> val xml = <outertag><dog>val1</dog><cat>val2</cat></outertag>
xml: scala.xml.Elem = <outertag><dog>val1</dog><cat>val2</cat></outertag>
scala> val cat = xml \\ "cat" text
cat: String = val2
scala> val dog = xml \\ "dog" text
dog: String = val1
cat1
将为“val2”;dog1
将为“val1”;goat
将为“未找到山羊”
更新:这里有一个更方便的方法获取标记名列表,并将其匹配项作为映射返回[String,String]
// Searches for all tags in the List and returns a Map[String, String].
def getNodeValues(x:scala.xml.NodeSeq, tags:List[String]) = {
tags.foldLeft(Map[String, String]()) { (a, b) => a(b) = simpleGetNodeValue(x, b)}
}
val tagsToMatch = List("dog", "cat")
val matchedValues = getNodeValues(xmlData, tagsToMatch)
如果运行该命令,匹配的值
将是映射(dog->val1,cat->val2)
希望有帮助
更新2:根据Daniel的建议,我正在使用双反斜杠操作符,它将下降到子元素中,随着XML数据集的发展,这可能会更好。scala>val XML=val1val2
scala> val xml = <outertag><dog>val1</dog><cat>val2</cat></outertag>
xml: scala.xml.Elem = <outertag><dog>val1</dog><cat>val2</cat></outertag>
scala> val cat = xml \\ "cat" text
cat: String = val2
scala> val dog = xml \\ "dog" text
dog: String = val1
xml:scala.xml.Elem=val1val2
scala>val cat=xml\\“cat”文本
cat:String=val2
scala>val dog=xml\\“dog”文本
狗:String=val1
scala>val xml=val1val2
xml:scala.xml.Elem=val1val2
scala>val cat=xml\\“cat”文本
cat:String=val2
scala>val dog=xml\\“dog”文本
狗:String=val1
我感觉最近有人在处理XML…:-)但是,我建议在第一个示例中使用双反斜杠而不是单反斜杠。(该死的stackoverflow一直在处理反斜杠)我并没有太多地使用XML——我只是想了解一下Scala。在任何情况下,我都在尝试清理简单的问题,以便您可以回答doozies,比如一些奇怪的Python转换。顺便说一句,对双反斜杠的调用很好。:)我感觉最近有人在处理XML…:-)但是,我建议在第一个示例中使用双反斜杠而不是单反斜杠。(该死的stackoverflow一直在处理反斜杠)我并没有太多地使用XML——我只是想了解一下Scala。在任何情况下,我都在尝试清理简单的问题,以便您可以回答doozies,比如一些奇怪的Python转换。顺便说一句,对双反斜杠的调用很好。:)谢谢你能给出一个使用屈服表达式的例子吗?或者至少是一个谈论它们的好网址。就像我说的,我是个新手(我不是这个意思)。通过定义一个返回值的函数——这里是Tuple2[String,String]——您现在有了一个可用的表达式,因为调用一个返回值的函数就是一个表达式。声明和初始化“val”本身就是一个语句,右侧(初始值)必须是表达式,而不是语句。这意味着右侧可以是文字值或函数调用,但不能是一个或多个语句。正是语句和表达式之间的这种区别经常鼓励我们编写这些小函数。谢谢!你能给出一个使用屈服表达式的例子吗?或者至少是一个谈论它们的好网址。就像我说的,我是个新手(我不是这个意思)。通过定义一个返回值的函数——这里是Tuple2[String,String]——您现在有了一个可用的表达式,因为调用一个返回值的函数就是一个表达式。声明和初始化一个“val”本身就是一个语句,右侧(初始v