flat lay photography of boxes of berries

使用 Apache Groovy 的展开运算符优化您的代码

通过展开运算符,增进您对 Apache Groovy 集合的了解。学习如何组织、组合……
首页 » 博客 » 使用 Apache Groovy 的展开运算符优化您的代码

通过展开运算符,增强您对 Groovy 集合的理解。本指南深入探讨如何使用它来组织、组合和更改列表和映射,最终提高代码的可读性和有效性。

我们已经介绍了 Closure 如何方便地操作列表或映射元素,并特别仔细地研究了排序。现在我们将看看展开运算符,它提供了一种不同的方式来对列表或映射的元素应用转换。(如果您尚未安装 Groovy,请阅读本系列的介绍 系列。)

Groovy 有两个相关的运算符,它们提供了一种简洁的方式来对 Collection 的所有成员执行操作——展开点运算符——以及将集合的成员“解集合”为单个元素——展开运算符。让我们看看如何使用它们使我们的 Groovy 代码更紧凑、更具表现力、更易读和更易于维护。

首先,展开运算符有助于合并列表和映射。
考虑一下这个

1  def l = [1, 5, 6, 7]
2  def s = [2, 3, 4]
3  l[2] = s
4  println "l $l"
5  l = [1, 5, 6, 7]
6  l = [*l.take(1), *s, *l.takeRight(l.size() - 1)]
7  println "l $l"

第一行定义了列表 l,其第一个和第二个元素值之间存在明显的间隔。

第二行定义了子列表 s,它可以放入 l 中的间隙。

第三行使用 List 接口的 putAt() 方法将子列表 s 插入到列表 l 中——行 l[2] = s 等效于 l.putAt(2, s)

第四行打印结果。

第五行将 l 重置为其原始值。

第六行使用 take() 方法获取 l 的第一个元素的子列表,并使用 takeRight() 方法获取 l 的剩余元素的子列表。通过在第 6 行的每个子列表前放置 * 或展开运算符,我们将它们“解列表”为它们的元素。

第七行打印结果。

让我们看看它是什么样子的

$ groovy Groovy17a.groovy
l [1, 5, [2, 3, 4], 7]
l [1, 2, 3, 4, 5, 6, 7]
$

请注意,第一次尝试使列表 l 中嵌入了子列表 s,而第二次尝试给了我们一个新的扁平列表。

我们可以对第一种情况下的 l 应用 flatten() 方法,以将子列表元素提升到列表中。

我们可以对映射执行与列表相同的过程,只需进行一个小的语法更改——* 运算符与冒号一起使用——如果 sm 是子映射,则 *:smsm 的成员提取到映射中。

*. 运算符是将方法应用于列表或映射的每个元素的一种方式。这是一个例子

1  def l = [1, 2, 3, 4, 5]
2  println "l $l"
3  println "l*.plus(2) ${l*.plus(2)}"
4  println "l*.multiply(2) ${l*.multiply(2)}"
5  println "l*.power(2) ${l*.power(2)}"

第一行定义了我们的测试列表,其中包含整数 1 到 5。

第二行打印列表。

第三行打印一个新列表,其元素均比 l 的原始元素大 2。

第四行打印一个新列表,其元素均是 l 的原始元素的两倍。

第五行打印一个新列表,其元素均是 l 的原始元素的平方。

运行它

$ groovy Groovy17b.groovy
l [1, 2, 3, 4, 5]
l*.plus(2) [3, 4, 5, 6, 7]
l*.multiply(2) [2, 4, 6, 8, 10]
l*.power(2) [1, 4, 9, 16, 25]
$

您可以使用 Listcollect() 方法产生相同的结果

l*.plus(2)

这产生的结果与

l.collect { e ->  e + 2 }

这种等效性表明,我们可以通过键从类实例列表或映射值中挖掘出字段值

1  def l = [
2 [temp:  96.3, gender: 'male',   pulse: 70],
3 [temp:  96.7, gender: 'male',   pulse: 71],
4 [temp:  96.9, gender: 'male',   pulse: 74],
5 [temp:  97.0, gender: 'male',   pulse: 80],
6 [temp:  97.1, gender: 'male',   pulse: 73],
7 [temp:  97.1, gender: 'male',   pulse: 75],
8 [temp:  97.1, gender: 'male',   pulse: 82],
9 [temp:  97.2, gender: 'male',   pulse: 64],
10 [temp:  97.3, gender: 'male',   pulse: 69],
11 [temp:  99.0, gender: 'female', pulse: 81],
12 [temp:  99.1, gender: 'female', pulse: 80],
13 [temp:  99.1, gender: 'female', pulse: 74],
14 [temp:  99.2, gender: 'female', pulse: 77],
15 [temp:  99.2, gender: 'female', pulse: 66],
16 [temp:  99.3, gender: 'female', pulse: 68],
17 [temp:  99.4, gender: 'female', pulse: 77],
18 [temp:  99.9, gender: 'female', pulse: 79],
19 [temp: 100.0, gender: 'female', pulse: 78],
20 [temp: 100.8, gender: 'female', pulse: 77]]
21  println "l*.temp ${l*.temp}"

运行它

$ groovy Groovy17c.groovy
l*.temp [96.3, 96.7, 96.9, 97.0, 97.1, 97.1, 97.1, 97.2, 97.3, 99.0, 99.1, 99.1, 99.2, 99.2, 99.3, 99.4, 99.9, 100.0, 100.8]
$

结论

展开运算符 * 是一种将集合的元素提取到周围集合中的方法。展开点运算符 *. 是一种将方法应用于集合的每个元素,或从类实例列表或映射中提取特定字段或键值对的方法。

这两种操作都可以使用 Groovy 中的其他工具实现,但是采用展开运算符,特别是展开点运算符提供的“将列表视为整体”或“将映射视为整体”的观点可能是一件好事。

呼叫所有 LISP 爱好者:对于展开运算符和展开点运算符,是否有任何我可能忽略的隐藏的亮点或独特的用例?

作者

留下评论

发表回复

如果您喜欢这篇文章,您可能也喜欢这些