Scala:如何将模式匹配功能应用于包含以下值的 csv 文件

Posted

技术标签:

【中文标题】Scala:如何将模式匹配功能应用于包含以下值的 csv 文件【英文标题】:Scala: How to apply the pattern matching function to a csv file which contains the below mentioned values 【发布时间】:2018-07-07 11:36:47 【问题描述】:
def matchcase(x:String):Int =  x match
        case "Iris-setosa" => 10
        case "Iris-virginica" => 20
        case "Iris-versicolor"=> 30
        case _ => 0

csv文件中的样本数据如下:

1,5.1,3.5,1.4,0.2,Iris-setosa
2,4.9,3,1.4,0.2,Iris-setosa
3,4.7,3.2,1.3,0.2,Iris-setosa
51,7,3.2,4.7,1.4,Iris-versicolor
52,6.4,3.2,4.5,1.5,Iris-versicolor
53,6.9,3.1,4.9,1.5,Iris-versicolor
103,7.1,3,5.9,2.1,Iris-virginica
104,6.3,2.9,5.6,1.8,Iris-virginica
105,6.5,3,5.8,2.2,Iris-virginica

【问题讨论】:

您的模式匹配代码看起来不错。有什么问题? 其实我想用 matchcase 函数替换整个文件中的文本。我们可以这样做吗。请提出一些想法。如果值进入一个新的字段(列)也很好。 我已尝试回答。 :) 希望对您有所帮助 【参考方案1】:

在你的评论中你提到了

其实我想用 matchcase 函数替换整个文件中的文本

假设你有问题中提到的数据和功能,你可以使用scala.io.Source.fromFile来读取文件

val data = scala.io.Source.fromFile("input file path")

调用你写的matchcase函数

val replacedData = data.getLines().map(_.split(",")).map(array => array.init.mkString(",")+","+matchcase(array.last))

最后写输出

new PrintWriter("path to output file")write(replacedData.mkString("\n")); close

你应该有一个包含以下数据的文件

1,5.1,3.5,1.4,0.2,10
2,4.9,3,1.4,0.2,10
3,4.7,3.2,1.3,0.2,10
51,7,3.2,4.7,1.4,30
52,6.4,3.2,4.5,1.5,30
53,6.9,3.1,4.9,1.5,30
103,7.1,3,5.9,2.1,20
104,6.3,2.9,5.6,1.8,20
105,6.5,3,5.8,2.2,20

希望回答对你有帮助

【讨论】:

这是我预期的输出。非常感谢【参考方案2】:

在 Scala 中通过正则表达式使用提取器模式

给定正则表达式

val regex = "[[0-9]|,|\\.]+([[a-zA-z]|\\-]+)".r

现在只需逐行匹配整个文本

lines.map 
  case regex(name) => Some(name)
  case _ => None

稍后使用您的matchCase 函数将字符串(名称)转换为数字 并将名称替换为数字

您正在寻找的代码

lines.map  line =>
  line match 
   case regex(name) => line.replace("[[a-zA-z]|\\-]+", matchcase(name).toString)
   case _ => line
  

Scala REPL

scala> val regex = "[[0-9]|,|\\.]+([[a-zA-z]|\\-]+)".r
regex: scala.util.matching.Regex = [[0-9]|,|\.]+([[a-zA-z]|\-]+)

scala> "1,5.1,3.5,1.4,0.2,Iris-setosa" match  case regex(str) => println(s"name: $str")
name: Iris-setosa

下一个

处理整个文本

scala> val text = """
     | 1,5.1,3.5,1.4,0.2,Iris-setosa
     | 2,4.9,3,1.4,0.2,Iris-setosa
     | 3,4.7,3.2,1.3,0.2,Iris-setosa
     | 51,7,3.2,4.7,1.4,Iris-versicolor
     | 52,6.4,3.2,4.5,1.5,Iris-versicolor
     | 53,6.9,3.1,4.9,1.5,Iris-versicolor
     | 103,7.1,3,5.9,2.1,Iris-virginica
     | 104,6.3,2.9,5.6,1.8,Iris-virginica
     | 105,6.5,3,5.8,2.2,Iris-virginica
     | """.stripMargin
text: String =
"
1,5.1,3.5,1.4,0.2,Iris-setosa
2,4.9,3,1.4,0.2,Iris-setosa
3,4.7,3.2,1.3,0.2,Iris-setosa
51,7,3.2,4.7,1.4,Iris-versicolor
52,6.4,3.2,4.5,1.5,Iris-versicolor
53,6.9,3.1,4.9,1.5,Iris-versicolor
103,7.1,3,5.9,2.1,Iris-virginica
104,6.3,2.9,5.6,1.8,Iris-virginica
105,6.5,3,5.8,2.2,Iris-virginica
"

scala> val lines = text.split("\n").filter(_.trim.nonEmpty)
lines: Array[String] = Array(1,5.1,3.5,1.4,0.2,Iris-setosa, 2,4.9,3,1.4,0.2,Iris-setosa, 3,4.7,3.2,1.3,0.2,Iris-setosa, 51,7,3.2,4.7,1.4,Iris-versicolor, 52,6.4,3.2,4.5,1.5,Iris-versicolor, 53,6.9,3.1,4.9,1.5,Iris-versicolor, 103,7.1,3,5.9,2.1,Iris-virginica, 104,6.3,2.9,5.6,1.8,Iris-virginica, 105,6.5,3,5.8,2.2,Iris-virginica)

scala> lines.map 
     |  case regex(name) => Some(name)
     |  case _ => None
     | 
res18: Array[Option[String]] = Array(Some(Iris-setosa), Some(Iris-setosa), Some(Iris-setosa), Some(Iris-versicolor), Some(Iris-versicolor), Some(Iris-versicolor), Some(Iris-virginica), Some(Iris-virginica), Some(Iris-virginica))

现在使用collect 并且只收集Some 的值

scala> res18.collect  case Some(value) => value 
res19: Array[String] = Array(Iris-setosa, Iris-setosa, Iris-setosa, Iris-versicolor, Iris-versicolor, Iris-versicolor, Iris-virginica, Iris-virginica, Iris-virginica)

scala> res19.mkString("\n")
res20: String =
Iris-setosa
Iris-setosa
Iris-setosa
Iris-versicolor
Iris-versicolor
Iris-versicolor
Iris-virginica
Iris-virginica
Iris-virginica

【讨论】:

以上是关于Scala:如何将模式匹配功能应用于包含以下值的 csv 文件的主要内容,如果未能解决你的问题,请参考以下文章

Spark记录-Scala模式匹配

有趣的Scala模式匹配

Scala_模式匹配

Scala_模式匹配

小记--------scala-模式匹配

Scala快速入门--模式匹配