震惊小伙伴的单行代码●Scala篇

几年前,函数式编程的复兴正值巅峰,一篇介绍 Scala 中 10 个单行函数式代码的博文在网上走红。很快地,一系列使用其他语言实现这些单行代码的文章也随之出现,比如 Haskell, Ruby, Groovy, Clojure, Python, C#, F#, CoffeeScript

每篇文章都令人印象深刻的揭示了这些语言中一些出色优秀的编程特征。编程高手们利用这些技巧提高编程速度、改进软件质量,编程初学者能从这些简洁的预防中学到各种编程语言的真谛。本《震惊小伙伴的单行代码系列》将逐一介绍这些各种编程语言单行代码文章,供大家学习参考。

1. 让列表中的每个元素都乘以2

map函数能将列表中的每个元素依次取出,并用指定的函数依次处理每个元素。在下面的例子里,我们将依次取出每个列表元素,并将它们依次乘以2。这些操作执行完成之后,返回的列表包含的元素个数不变。这是跟reduceLeftfoldLeft 等只返回一个值的函数的不同之处。

(1 to 10) map { _ * 2 }

2. 求列表中的所有元素之和

reduceLeft函数最常用的功能是求列表里的所有元素之和。下面的例子里,我们使用range函数创建一个11000的列表,然后用reduceLeft遍历每个元素,相加求和。(附增用更简单的内置函数sum求和。)

(1 to 1000).reduceLeft( _ + _ )
或
(1 to 1000).sum

3. 判断一个字符串中是否存在某些词

下面的例子中,如果字符串中包含列表中的某个单词,则返回真,否则假。我常使用这个技巧来检查一条微博里是否含有我感兴趣的词汇。从技术上将下面是三行代码,但前两行只能算作变量。

val wordList = List("scala", "akka", "play framework", "sbt", "typesafe")
val tweet = "This is an example tweet talking about scala and sbt."

(wordList.foldLeft(false)( _ || tweet.contains(_) ))
或
wordList.exists(tweet.contains)

4. 读取文件

如果你是使用Java编程的程序员,这一行代码也许会让你惊讶,而在Scala里用一行代码就能读取和分析文件是很常见的事。下面是读取一个文件的两个例子,一个将整个文件读取都一个字符串里,另外一个读取文件并按行装入一个列表里。

val fileText = io.Source.fromFile("data.txt").mkString

val fileLines = io.Source.fromFile("data.txt").getLines.toList

5. 祝你生日快乐!

一行代码打印出“祝你生日快乐!”歌。下面的例子里展示了Scala的三元操作和 mapforeach 的混合使用。

(1 to 4).map { i => "Happy Birthday " + (if (i == 3) "dear NAME" else "to You") }.foreach { println }

6. 过滤列表中的数值

使用 partition 设定的条件将列表中的数字分为两类。下面的例子将学生按分数分为两个列表。

val (passed, failed) = List(49, 58, 76, 82, 88, 90) partition ( _ > 60 )

7. 获取XML web service数据并分析

因为XML是Scala中的一个原生结构,所有,分析XML是非常容易的。下面的例子是获取并分析Twitter feed的例子。

val results = XML.load("http://search.twitter.com/search.atom?&q=scala")

8. 找到列表中最小或最大的一个数字

下面的几个例子都使用了reduceLeft来遍历一个列表中的数据,并使用指定的函数分析它们。附增了使用更简单的min/max方法。

List(14, 35, -7, 46, 98).reduceLeft ( _ min _ )
List(14, 35, -7, 46, 98).min

List(14, 35, -7, 46, 98).reduceLeft ( _ max _ )
List(14, 35, -7, 46, 98).max

9. 并行处理

Scala里有一个叫做”parallel collections”的集合类型,它能利用多核处理器来处理批量操作,例如foreach, map, filter, 等… 这里有一个视频可以参考。

下面的例子并不完整,但能很好的说明如何使用parallel collections并行处理。假设你有一堆数据在dataList里,有一个函数processItem来处理它们,但很耗CPU。下面的这行代码就能让你使用并行技术处理你的数据。

val result = dataList.par.map( line => processItem(line) )

10. “Sieve of Eratosthenes”算法

好吧,这个并不是很使用,技术上将不是一行,因为它使用了之前定义好的操作符,尽管不好阅读,但很强大。Daniel Sobral发明了Sieve of Eratosthenes算法,可以用来判断一个数字是否是素数

(n: Int) => (2 to n) |> (r => r.foldLeft(r.toSet)((ps, x) => if (ps(x)) ps -- (x * x to n by x) else ps))

需要使用预定义的|>操作符,它是一个从 F# 语言里借来的语法。你可以参考Steve Gilham的博客里的例子。

分享这篇文章:

发表评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据