不同Java.net语言中类似的函数结构分析

这篇文章主要介绍“不同Java.net语言中类似的函数结构分析”,在日常操作中,相信很多人在不同Java.net语言中类似的函数结构分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”不同Java.net语言中类似的函数结构分析”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

网站建设哪家好,找成都创新互联!专注于网页设计、网站建设、微信开发、小程序设计、集团企业网站建设等服务项目。为回馈新老客户创新互联还提供了永顺免费建站欢迎大家使用!

过滤

在过滤 函数中,您可指定一个布尔值条件(通常为一个高阶函数的形式),将它应用到一个集合。该函数返回集合的子集,其中的元素与该条件匹配。过滤与查找 函数紧密相关,后者返回集合中第一个匹配的元素。

Scala

Scala 拥有多个过滤函数变体。最简单的情形基于传递的条件来过滤某个列表。在第一个示例中,我创建一个数字列表。然后使用了 filter() 函数,并传递了一个代码块,指定了所有元素都可以被 3 整除的条件:

val numbers = List.range(1, 11)numbers filter (x => x % 3 == 0)// List(3, 6, 9)

我可依靠隐式的参数来创建该代码快的更加简洁的版本:

numbers filter (_ % 3 == 0)// List(3, 6, 9)

第二个版本不那么冗长,因为在 Scala 中,您可以将参数替换为下划线。两个版本都可以得到相同的结果。

过滤操作的许多示例都使用了数字,但 filter() 适用于任何集合。此示例将 filter() 应用到一个单词列表来确定 3 字母单词:

val words = List("the", "quick", "brown", "fox", "jumped", "over", "the", "lazy", "dog")words filter (_.length == 3)// List(the, fox, the, dog)

Scala 中的另一个过滤函数变体是 partition() 函数,它将一个集合拆分为多个部分。这种拆分基于您传递的高阶函数来确定分离条件。在这里,partition() 函数将返回两个列表,它们依据哪些列表成员可被 3 整除来进行拆分:

numbers partition (_ % 3 == 0)// (List(3, 6, 9),List(1, 2, 4, 5, 7, 8, 10))

filter() 函数返回一个匹配元素集合,而 find() 仅返回第一个匹配元素:

numbers find (_ % 3 == 0)// Some(3)

但是,find() 的返回值不是匹配的值本身,而是一个包装在 Option 类中的值。Option 有两个可能的值:Some 或 None。像其他一些函数式语言一样,Scala 使用 Option 作为一种约定来避免在缺少某个值时返回 null。Some() 实例包装实际的返回值,在 numbers find (_ % 3 == 0) 的情况下,该值为 3。如果我尝试查找某个不存在的值,那么返回值将为 None:

numbers find (_ < 0)// None

Scala 还包含多个函数,它们基于一个判定函数来处理一个集合并返回值或丢弃它们。takeWhile() 函数返回集合中满足判定函数的最大的值集:

List(1, 2, 3, -4, 5, 6, 7, 8, 9, 10) takeWhile (_ > 0)// List(1, 2, 3)

dropWhile() 函数跳过满足判定条件的最大元素数量:

words dropWhile (_ startsWith "t")// List(quick, brown, fox, jumped, over, the, lazy, dog)

Groovy

Groovy 不是一个函数式语言,但它包含许多函数范例,一些范例的名称源自脚本语言。例如,在函数式语言中,该函数在传统上被称为 filter() 的函数,就是 Groovy 中的 findAll() 方法:

(1..10).findAll {it % 3 == 0}// [3, 6, 9]

像 Scala 的过滤函数一样,Groovy 可处理所有类型,包括字符串:

def words = ["the", "quick", "brown", "fox", "jumped", "over", "the", "lazy", "dog"]words.findAll {it.length() == 3}// [The, fox, the, dog]

Groovy 还有一个类似 partition() 的函数,称为 split():

(1..10).split {it % 3}// [[1, 2, 4, 5, 7, 8, 10], [3, 6, 9]]

split() 方法的返回值是一个嵌套数组,就像 Scala 中从 partition() 返回的嵌套列表。

Groovy 的 find() 方法返回集合中第一个匹配的元素:

(1..10).find {it % 3 == 0}// 3

不同于 Scala,Groovy 遵循 Java 约定,在 find() 未能找到元素时返回 null:

(1..10).find {it < 0}// null

Groovy 还拥有 takeWhile() 和 dropWhile() 方法,它们具有与 Scala 的版本类似的语义:

[1, 2, 3, -4, 5, 6, 7, 8, 9, 10].takeWhile {it > 0}// [1, 2, 3]words.dropWhile {it.startsWith("t")}// [quick, brown, fox, jumped, over, the, lazy, dog]

与 Scala 示例中一样,dropWhile 被用作一个专门的过滤器:它丢弃与判定条件匹配的最大前缀,仅过滤列表的第一部分:

def moreWords = ["the", "two", "ton"] + wordsmoreWords.dropWhile {it.startsWith("t")}// [quick, brown, fox, jumped, over, the, lazy, dog]

Clojure

Clojure 拥有令人震惊的集合操作例程数量。由于 Clojure 的动态类型,其中许多例程都是通用的。许多开发人员倾向于使用 Clojure,因为它的集合库非常丰富和灵活。Clojure 使用传统的函数式编程名称,如 (filter ) 函数所示:

(def numbers (range 1 11))(filter (fn [x] (= 0 (rem x 3))) numbers); (3 6 9)

像其他语言一样,Clojure 为简单的匿名函数提供了简洁的语法:

(filter #(zero? (rem % 3)) numbers); (3 6 9)

而且与其他语言中一样,Clojure 的函数适用于任何适用的类型,比如字符串:

(def words ["the" "quick" "brown" "fox" "jumped" "over" "the" "lazy" "dog"])(filter #(= 3 (count %)) words); (the fox the dog)

Clojure 的 (filter ) 返回类型为 Seq,它通过圆括号来描述。Seq 是 Clojure 中的顺序集合的核心抽象。

映射

所有 Java 下一代语言中常见的第二个主要的函数变形是映射。映射函数接受一个高阶函数和一个集合,然后向每个元素应用传递的函数并返回一个集合。返回的集合(不同于过滤)的大小与原始集合相同,但更新了值。

Scala

Scala 的 map() 函数接受一个代码块并返回转换的集合:

List(1, 2, 3, 4, 5) map (_ + 1)// List(2, 3, 4, 5, 6)

map() 函数适用于所有适用的类型,但它不一定返回集合元素的已转换集合。在此示例中,我在一个字符串中返回所有元素的大小列表:

words map (_.length)// List(3, 5, 5, 3, 6, 4, 3, 4, 3)

在函数式编程语言中常常会产生嵌套列表,以至于嵌套列表对解除嵌套(通常称为扁平化)的库支持很常见。以下是扁平化一个嵌套列表的示例:

List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9)) flatMap (_.toList)// List(1, 2, 3, 4, 5, 6, 7, 8, 9)

获得的 List 中仅包含元素,删除了额外的基础架构。flatMap 函数也适用于可能未以传统方式嵌套的数据结构。例如,您可将一个字符串视为一个嵌套字符系列:

words flatMap (_.toList)// List(t, h, e, q, u, i, c, k, b, r, o, w, n, f, o, x, ...

Groovy

Groovy 还包含多个称为 collect() 的映射变体。默认的变体接受一个代码块,以便将该变体应用到集合的每个元素:

(1..5).collect {it += 1}// [2, 3, 4, 5, 6]

像其他语言一样,Groovy 允许对简单的匿名高阶函数使用简写;it 保留字用于替代单独的参数。

collect() 方法适用于您可向其提供合理的判定条件的任何集合,比如一个字符串列表:

def words = ["the", "quick", "brown", "fox", "jumped", "over", "the", "lazy", "dog"]words.collect {it.length()}// [3, 5, 5, 3, 6, 4, 3, 4, 3]

Groovy 还有一个类似于 flatMap() 的折叠内部结构的方法,称为 flatten():

[[1, 2, 3], [4, 5, 6], [7, 8, 9]].flatten()// [1, 2, 3, 4, 5, 6, 7, 8, 9]

flatten() 方法也适用于不太明显的集合,比如字符串:

(words.collect {it.toList()}).flatten()// [t, h, e, q, u, i, c, k, b, r, o, w, n, f, o, x, j, ...

Clojure

Clojure 包含一个 (map ) 函数,它接受一个高阶函数(其中包含运算符)和一个集合:

(map inc numbers); (2 3 4 5 6 7 8 9 10 11)

(map ) 的第一个参数可以是任何接受单个参数的函数:命名函数、匿名函数或已存在的函数,比如递增其参数的 inc。此示例中演示了更典型的匿名语法,它生成一个字符串中的单词长度的集合:

(map #(count %) words); (3 5 5 3 6 4 3 4 3)

Clojure 的 (flatten ) 函数类似于 Groovy 的:

(flatten [[1 2 3] [4 5 6] [7 8 9]]); (1 2 3 4 5 6 7 8 9)

折叠/缩减

在 3 种 Java 下一代语言中,第三个常见函数在名称上拥有最多变体和许多细微的区别。foldLeft 和 reduce 是一个名为 catamorphism 的列表操作概念上的特定变体,该概念是列表折叠的一种泛化。在此示例中,“折叠左侧” 表示:

使用一个二进制函数或运算符将列表的第一个元素与第二个元素相结合,创建一个新的第一个元素。重复第一步,直到列表用完且您得到一个单一元素。

请注意,这是您在对一组数字求和时所做的操作:从 0 开始,加第一个元素,将结果与第二个元素相加,一直执行此操作,直到列表元素被用完为止。

Scala

Scala 拥有最丰富的折叠运算集合,这是因为它在一定程度上简化了动态类型的 Groovy 和 Clojure 中没有的多种类型场景。缩减函数常用于执行求和:

List.range(1, 10) reduceLeft((a, b) => a + b)// 45

提供给 reduce() 的函数通常是一个接受两个参数,并返回单个结果的函数或运算符,以便可以使用一个列表。您可以使用 Scala 的语法糖来缩短函数定义:

List.range(1, 10).reduceLeft(0)(_ + _)// 45

reduceLeft() 函数假设第一个元素是运算的左侧。对于相加等运算符,操作数的位置无关紧要,但放置顺序对相除等运算至关重要。如果希望反转运算符应用的顺序,可以使用 reduceRight():

List.range(1, 10) reduceRight(_ - _)// 5

了解何时可使用缩减等高级抽象是掌握函数编程的一个关键。此示例使用 reduceLeft() 来确定集合中最常的单词:

words.reduceLeft((a, b) => if (a.length > b.length) a else b)// jumped

缩减和折叠运算拥有重叠的功能,它们具有细微的差别,但这不属于本文的讨论范围。但是,通常可以看到它们的一个明显区别。在 Scala 中,签名 reduceLeft[B >:A](op:(B, A) => B):B 表明惟一想要的参数就是组合元素的函数。初始值应该是集合中的第一个值。相对而言,签名 foldLeft[B](z:B)(op:(B, A) => B):B 表示结果的一个初始种子值,所以您可以返回与列表元素类型不同的类型。

以下是一个使用 foldLeft 对集合求和的示例:

List.range(1, 10).foldLeft(0)(_ + _)// 45

Scala 支持运算符重叠,所以两个常见的折叠操作 foldLeft 和 foldRight 分别拥有相应的运算符:/: 和 :\。因此,您可以使用 foldLeft 创建 sum 的简洁版本:

(0 /: List.range(1, 10)) (_ + _)// 45

类似地,要找到一个列表中每个元素的级联区别(求和运算的反向操作,无可否认这种需求很少见),您可以使用 foldRight() 函数或 :\ 运算符:

(List.range(1, 10) :\ 0) (_ - _)// 5

Groovy

Groovy 通过使用重叠来支持与 Scala 的 reduce() 和 foldLeft() 选项相同的功能,从而进入缩减类别。该函数的一个版本接受一个初始值。此示例使用 inject() 方法生成一个集合的总和:

(1..10).inject {a, b -> a + b}// 55

替代形式接受一个初始值:

(1..10).inject(0, {a, b -> a + b})// 55

Groovy 拥有一个比 Scala 或 Clojure 小得多的函数库 — Groovy 是一种不强调函数式编程的多范例编程,看到这种情况毫不奇怪。

Clojure

Clojure 主要是一种函数式编程语言,所以它支持 (reduce )。(reduce ) 函数接受一个可选的初始值,以便同时涵盖 Scala 所处理的 reduce() 和 foldLeft() 情形。(reduce ) 函数没有给用户带来任何惊喜。它接受一个需要两个参数的函数和一个集合:

(reduce + (range 1 11)); 55

Clojure 将对类似 reduce 的功能的高级支持包含在一个名为 reducers 的库中,后面的一期文章将会介绍这个库。

到此,关于“不同Java.net语言中类似的函数结构分析”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注创新互联网站,小编会继续努力为大家带来更多实用的文章!


分享文章:不同Java.net语言中类似的函数结构分析
URL链接:http://cdiso.cn/article/ghhsjc.html

其他资讯