Groovy是Java的近乎完美的补充,为我的使用提供了一个紧凑,高度表达且兼容的脚本环境。 当然,Groovy并不完全完美。 与任何编程语言一样,其设计基于需要权衡的一系列权衡,才能产生高质量的结果。 但是对我来说,Groovy的优点远大于缺点,这使其成为我的数据分析工具包中不可或缺的一部分。 在一系列文章中,我将解释如何以及为什么。
在1990年代后期,我发现自己对Java编程语言越来越感兴趣,越来越多地将它用于AWK和我以前在C语言中所做的工作。到2005年,低成本和强大Linux的功能说服了我放弃我心爱但老化的Sun工作站。 在我的工作中,AWK, sort(1)
, paste(1)
和join(1)
在Linux环境中竞争激烈,首先是Perl ,然后是Python 。 Perl的语法从未达到我的口味,但我发现Python引人入胜,因为它的可读性,“包含电池”的理念以及与各种其他内容(如定界文本文件,电子表格,数据库,图形化,除了一件事之外,它并没有给我带来对整个Java Universe的干净,透明的访问,而这对我的工作流越来越重要。
然后我“发现”了Groovy。
分隔的文本文件
在以AWK为中心的数据分析领域中,使用数据通常意味着使用定界的文本文件。 这是由两个因素共同造成的。 首先是Unix文本文件处理工具通常认识到分隔符文本文件中经常遇到数据,即文本文件,其行以换行符分隔,被分隔为字段,并以字段分隔符分隔(例如, TAB或其他一些不寻常的字符,例如竖线)。 第二个原因是电子表格之类的工具倾向于提供一种“导出”功能,该功能可产生逗号分隔的值文本文件,按照惯例,其第一行是每个字段的名称,而其余行则由用逗号分隔的数据字段组成(或者,在使用逗号作为小数点的国家/地区,请使用分号)。
AWK非常擅长处理带分隔符的文本文件,除非字段或行分隔符也出现在数据中。 此外,AWK还确实适合用于编写对呈现的数据做出React的代码节,并且在数据呈现复杂(例如,层次结构)时,吸引力并不那么大。 AWK也不真正提供在不通过中间定界文本格式的情况下从关系数据库,电子表格或二进制格式(例如dBase)中读取或写入数据的任何好方法。
在这里,更完整的编程语言(例如Python或Groovy)开始变得有趣。 但是,在介绍这类直接集成示例之前,我将先回到带分隔符的文本。 让我们写一些代码! 但是首先,让我们获取一些数据! 但是,等等-我们最好先安装Groovy。
Groovy
找出如何安装Groovy的最好方法是转到groovy-lang.org上的安装说明 。 我更喜欢为此目的使用SDKMAN (在安装说明的中间记录),但是您也可以在存储库中安装该版本。 请注意,Java是先决条件。 这些天来,我使用Java8。同样,您可以在存储库中安装该版本。
获取数据
有了Groovy之后,就可以使用浏览器从世界银行站点访问开放的世界人口数据 。 在右侧,您将看到“ 下载”按钮。 以CSV格式获取数据; 它压缩在名为API_SP.POP.TOTL_DS2_en_csv_v2的目录中。 将该目录解压缩到系统上的合适位置。 然后打开一个终端窗口, cd
到该目录中。
最后-一些代码!
这是一个简单的Groovy脚本,用于读取您下载的CSV文件之一并将其打印到终端窗口中:
该脚本很好地概述了Groovy为Java程序员提供的功能。
首先, String mdCountryCSV = ...
这就像Java一样-我们正在声明一个初始化为String
文字的String
变量。 哦,是的,在大多数情况下,Groovy允许我们删除行尾分号。
接下来, new File(mdCountryCSV).withReader { reader ->
,在四行之后用}
其关闭。 new File()
部分也和Java一样。 但是,Groovy增强了许多java.lang.*
, java.io.*
, java.util.*
和标准Java库的其他部分。 在这种情况下,Groovy使用名为withReader
的方法增强了File类。 此方法接受闭包作为参数,在这种情况下,我们将其表示为代码块{ reader -> ... }
。 reader ->
将闭包的参数定义为变量reader
。
Groovy的新颖性完成了什么? 从功能withReader
, withReader
创建一个Reader
实例并调用该实例的关闭代码,并将该实例分配给变量reader
,最后关闭创建的File实例并释放其资源并处理发生的任何错误。 实际上,这使Groovy程序员可以将匿名方法声明为其他方法调用的参数。 而且,在封闭物内部可获得周围环境,而没有任何特殊的场所。
接下来, reader.eachLine { line ->
,在两行之后被}
关闭。 再次,我们看到了Groovy增强的Reader
方法, eachLine
以闭包作为参数调用,在这种情况下,我们用{ line -> ... }
。 在这里, Reader
实例为读取的文件的每一行调用闭包。
最后, println line
仅打印由Reader
实例读取的行。 Groovy在这里向我们展示了可以省略方法调用参数的括号,并且实际上它具有import System.out
作为执行代码的序言。
将此代码块另存为ex01.groovy
,与数据保存在同一目录中,并从终端命令行执行以下命令:
groovy ex01.groovy
你看到了什么?
在这一点上,值得注意的是,Groovy还悄悄地取消了可能在执行相同任务的Java程序中需要进行的导入和公共类定义。
处理领域
到目前为止,我们的Groovy脚本已经处理了行定界符,但尚未将行拆分为字段。 快速检查文件Metadata_Country_API_SP.POP.TOTL_DS2_en_csv_v2.csv会发现它是最复杂的CSV文件类型,它使用逗号作为字段分隔符,并引用可以包含字段或行分隔符的字段。
看第三行,关于安哥拉; 在第四个字段中,出现短语“基于国际货币基金组织的数据,国民账户”。 在第9行中,对于阿根廷,不仅逗号出现在同一字段中,而且回车/换行符对也出现。 最后,在第199行中,该字段包含一个双引号字符,该字符显示为两个连续的双引号。 一个“带引号的引号”,不要与两个连续的双引号作为一个字段的唯一内容混淆,这意味着一个空字段。 丑陋!
在AWK中,处理这种杂乱的东西并不令人愉快。 但是,在Groovy中,我们可以使用称为opencsv的高级Java库。 从SourceForge 下载.jar文件 。 将该.jar文件放在Groovy的默认查找路径中,即您的主目录中.groovy / lib子目录中。
在这一点上,第一个程序可以变为现场感知的:
将此文件另存为ex02.groovy在同一目录中,并使用groovy
命令运行它。
这里有什么新消息?
首先,我们必须导入CSVReader
功能。 然后我们创建一个CSVReader
从传授给我们读者实例withReader
。 最后,我们打印CSVReader
实例产生的字段。 在这里,我们使用Groovy放在每个对象上的each
方法以及opencsv提供的行拆分以处理文件中的行。 csvReader.each { fields ->
将每一行分成几个字段,即字符串数组。 我们可以将第一个字段称为fields[0]
,将第二个fields[1]
称为fields[1]
,依此类推。
鉴于这种CSV文件的第一行提供了字段名称,我们可以调整上面的代码以按名称引用字段,如下所示:
import
com.opencsv.CSVReader
String mdCountryCSV
=
"Metadata_Country_API_SP.POP.TOTL_DS2_en_csv_v2.csv"
new
File
( mdCountryCSV
) .
withReader
{ reader
-> CSVReader csvReader
=
new CSVReader
( reader
)
String
[
] csvFieldNames
= csvReader.
readNext
(
)
HashMap fieldValuesByName
=
new
HashMap
(
)
csvReader.
each
{ fieldValuesByNumber
->
csvFieldNames.
eachWithIndex
{ name, number
->
fieldValuesByName
[ name
]
= fieldValuesByNumber
[ number
]
}
println
"fieldValuesByName[ \" Country Code \" ] = "
+
fieldValuesByName
[
"Country Code"
]
+
" fieldValuesByName[ \" IncomeGroup \" ] = "
+
fieldValuesByName
[
"IncomeGroup"
]
}
}
将此ex03.groovy
另存为ex03.groovy
并在同一目录中运行。
在上面的代码中,我们readNext
从CSVReader
实例调用readNext
以获取第一条记录,并将字段名称保存在String
数组中。 然后,每次读取记录时,我们each
对字段名称执行each
方法,以将csvReader.each()
传递的字段数组中的值复制到映射中,该映射中的键为字段名称,而值来自于记录上的相应字段。
println
语句显示我们通过名称访问字段值,例如fieldValuesByName["Country Code"]
。
接下来要去哪里?
这可能是很多Groovy入门的基础。 以下是增强体验的良好参考:
- Groovy语言站点包含示例和参考文档
- Tim Roes为Java开发人员提供的有关Groovy的不错的教程
- Haki先生(别名Hubert Klein Ikkink) 出色的Groovy帖子系列
还提供了大量Groovy书籍,并对语言进行了很好的介绍。
Groovy系列的下一部分将进一步介绍已经介绍的主题:制作最后一个示例groovier,读取多个CSV文件,链接它们的数据以及编写复合/摘要。
您对编写“入门指南”文章有想法吗? 提交您的故事建议 。