十个惊人的Scala集合操作函数

十个惊人的Scala集合操作函数
当我操作 Scala 集合时,我一般会进行两类操作:转换操作(transformation )和行动操作(actions)(有些人喜欢叫他为聚合操作)。第一种操作类型将集合转换为另一个集合,第二种操作类型返回某些类型的值。

本文我将集中介绍几个日常工作必备的 [Scala(https://www.iteblog.com/archives/tag/scala/) 集合函数,如转换函数和聚合函数。文章最后,我会展示如何结合这些函数以解决具体问题。

文章目录
· 1 最大值和最小值

· 2 Filter

· 3 Flatten

· 4 欧拉图函数(Euler Diagram函数)

· 5 map列表元素

· 6 flatMap

· 7 对整个集合进行条件检查

· 8 对集合进行分组

· 9 Fold

· 10 您最喜欢的函数

· 11 总结

十个惊人的scala集合操作函数
https://www.iteblog.com/archives/1946.html

最大值和最小值
  我们先从动作函数(
action function)开始。在序列中查找最大或最小值是一个极常见的需求,较常用于面试问题和算法。还记得 Java 中的代码行吗?如下:

int[] arr = {11, 2, 5, 1, 6, 3, 9};

int to = arr.length - 1;

int max = arr[0];

for (int i = 0; i < to; i++) {

    if (max < arr[i+1])

        max = arr[i+1];

}

  

System.out.println(max);

问题:怎么在List 中找到最大/最小值呢?

Scala 推荐了一个很赞的解决方案:

val numbers = Seq(11, 2, 5, 1, 6, 3, 9) 

 numbers.max //11 

numbers.min //1

但实际操作的数据更加复杂。下面我们介绍一个更高级的例子,其中包含一个书的序列(查看源代码案例)。

case class Book(title: String, pages: Int)

 val books = Seq(

  Book("Future of Scala developers", 85),

  Book("Parallel algorithms", 240),

  Book("Object Oriented Programming", 130),

  Book("Mobile Development", 495)

)

  

//Book(Mobile Development,495)

books.maxBy(book => book.pages)

  

//Book(Future of Scala developers,85)

books.minBy(book => book.pages)

如上所示,
minBy & maxBy方法解决了复杂数据的问题。你只需选择决定数据最大或最小的属性。

Filter
你过滤过集合吗?比如,筛选价格大于10美元的条目,或挑选年龄在24岁以下员工等,所有这些操作属于过滤。
让我们举例说明:过滤一个数字List,只获取奇数的元素。

val numbers = Seq(1,2,3,4,5,6,7,8,9,10)

 numbers.filter(n **=**> n **%** 2 **==** 0)

然后加大难度,我想获取页数大于
120页的书。

val books = Seq(

  Book("Future of Scala developers", 85),

  Book("Parallel algorithms", 240),

  Book("Object Oriented Programming", 130),

  Book("Mobile Development", 495)

)

  

books.filter(book => book.pages >= 120)

实际上,过滤是一个转换类型的方法,但是比运用min和max方法简单。

还有一个与filter类似的方法是filterNot。它的名字就体现了它的作用。如果你还是不了解它的实际用途,你可以在一个示例中,用filterNot替换filter 方法。

Flatten
我想大多数朋友都没听说过这个功能。其实它很好理解,我们来举例说明:

val abcd = Seq('a', 'b', 'c', 'd')

val efgj = Seq('e', 'f', 'g', 'h')

val ijkl = Seq('i', 'j', 'k', 'l')

val mnop = Seq('m', 'n', 'o', 'p')

val qrst = Seq('q', 'r', 's', 't')

val uvwx = Seq('u', 'v', 'w', 'x')

val yz = Seq('y', 'z')

val alphabet = Seq(abcd, efgj, ijkl, mnop, qrst, uvwx, yz)

// List(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z)

alphabet.flatten

当有一个集合的集合,然后你想对这些集合的所有元素进行操作时,就会用到
flatten。

欧拉图函数(Euler Diagram函数)
不要紧张!接下来的操作大家都熟知:差集、交集和并集。以下示例能很好地解释
Euler Diagram 函数:

val num1 = Seq(1, 2, 3, 4, 5, 6)

val num2 = Seq(4, 5, 6, 7, 8, 9)

//List(1, 2, 3)

num1.diff(num2)

//List(4, 5, 6)

num1.intersect(num2)

//List(1, 2, 3, 4, 5, 6, 4, 5, 6, 7, 8, 9)

num1.union(num2)

上述示例中的 union保留了重复的元素。如果我们不需要重复怎么办?这时可以使用
distinct函数:

//List(1, 2, 3, 4, 5, 6, 7, 8, 9)

num1.union(num2).distinct

下面是上述功能的图示:

map列表元素
map 是 Scala 集合最常用的一个函数。它的功能十分强大:

val numbers = Seq(1,2,3,4,5,6)

//List(2, 4, 6, 8, 10, 12)

numbers.map(n **=**> n * 2)

val chars = Seq('a', 'b', 'c', 'd')

//List(A, B, C, D)

chars.map(ch **=**> ch.toUpper)

map 函数的逻辑是遍历集合中的元素并对每个元素调用函数。你也可以不调用任何函数,保持返回元素本身,但这样 map无法发挥作用,因为你在映射过后得到的是同样的集合。

flatMap
我很难具体说明flatMap 的使用场合,因为很多不同的情况下都会用到 flatMap。如果大家仔细观察,就会发现flatMap 是由下列这两个函数组成的:map & flatten
现在,假设我们想知道字母表中的大写字母和小写字母的排列情况:

val abcd = Seq('a', 'b', 'c', 'd')

//List(A, a, B, b, C, c, D, d)

abcd.flatMap(ch **=**> List(ch.toUpper, ch))

因为这篇文章是关于集合功能的介绍,所以此处略过
Future 和 Option 的示例。

对整个集合进行条件检查
有一个场景大家都知道,即确保集合中所有元素都要符合某些要求,如果有哪怕一个元素不符合条件,就需要进行一些处理:

val numbers = Seq(3, 7, 2, 9, 6, 5, 1, 4, 2)

//ture

numbers.forall(n **=**> n < 10)

//false

numbers.forall(n **=**> n > 5)

而forall 函数就是为处理这类需求而创建的。

对集合进行分组
你是否尝试过将一个集合按一定的规则拆分成两个新的集合?比如,我们把某个集合拆分成偶数集和奇数集,partition 函数可以帮我们做到这一点:

val numbers = Seq(3, 7, 2, 9, 6, 5, 1, 4, 2)

//(List(2, 6, 4, 2), List(3, 7, 9, 5, 1))

numbers.partition(n **=**> n **%** 2 **==** 0)

Fold
另一个流行的操作是fold。
在Scala 的上下文中,通常可以考虑 foldLeft 和 foldRight。他们是从不同的方面做同样的工作:

val numbers = Seq(1, 2, 3, 4, 5)

//15

numbers.foldLeft(0)((res, n) **=**> res + n)

在第一对括号中,我们放一个起始值。
在第二对括号中,我们定义需要对数字序列的每个元素执行的操作。
第一步,n = 0,然后它根据序列元素变化。
另一个关于foldLeft 的例子,计算字符数:

val words = Seq("apple", "dog", "table")

//13

words.foldLeft(0)((resultLength, word) **=**> resultLength + word.length)

您最喜欢的函数
经过了上面一系列的列举,从Scala集合找到你最喜欢的函数是很酷的(cool)。请大家在评论中写下它,并提供其使用的例子。

最近我通过了一个编译测试,任务的内容是:给你一个String S,你需要找到包含大写和小写字符,但不包含数字的最长子字符串。
比如: dP4knqw1QAp
答案: QAp
那么我们如何使用Scala集合函数来解决这个问题呢:

def theLongest(s: String): String = {

  s.split ("[0-9]")

    .filter (_.exists (ch => ch.isUpper))

    .filter (_.exists (ch => ch.isLower))

    .maxBy (_.length)

}

上面的函数解决了这个问题。如果输入字符串不包含任何合适的子字符串,将会抛出
UnsupportedOperationException。

总结
Scala具有令人难以置信的强大的集合API,你可以利用它做很多的事情。 此外,相同的事情可以以不同的方式进行,例如: 上面的欧拉函数例子。 Scala的API是很丰富的,我们需要很多时间和练习来学习它。

参考:
10 amazing scala collection functions

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容