第十章 Scala 容器基础(十九):把序列分解成子集(group by,partition等)

Problem

    你想要基于一种算法或者规则,把一个序列切分为两个或者多个子集。

Solution

    使用groupBy,partition,span,splitAt方法可以把一个集合切分成子集合。sliding和unzip方法也可以用来把集合切分成子集合,尽管sliding可以产生许多子序列,unzip则主要用来拆分二元祖。

    groupy,partition和span方法可以让你把一个集合按一个方法定义切分成子集合,splitAt让你按集合下标切分一个集合为两个子集合:

scala> val x = List(15, 10, 5, 8, 20, 12)
x: List[Int] = List(15, 10, 5, 8, 20, 12)

scala> x.groupBy(_ > 10)
res19: scala.collection.immutable.Map[Boolean,List[Int]] = Map(false -> List(10, 5, 8), true -> List(15, 20, 12))

scala> x.partition(_ > 10)
res20: (List[Int], List[Int]) = (List(15, 20, 12),List(10, 5, 8))

scala> x.partition(_ > 10)
res20: (List[Int], List[Int]) = (List(15, 20, 12),List(10, 5, 8))

scala> x.span(_ < 20)
res21: (List[Int], List[Int]) = (List(15, 10, 5, 8),List(20, 12))

scala> x.splitAt(2)
res22: (List[Int], List[Int]) = (List(15, 10),List(5, 8, 20, 12))

    groupBy(p)方法会把一个集合根据你提供的方法切分成一个map。Map中key=true对应的value是所有使p返回true的集合元素组成的新集合,key=flase对应的value是所有使p返回false的元素组成的新集合。

    方法partition(p),span(p)和splitAt(n)会创建一个二元祖,二元祖的每个元素都是和原集合类型相同的集合。partiton会把集合的所有元素遍历一遍,满足条件p的元素进二元祖第一个集合,不满足条件p的元素进二元祖第二个集合。span方法会从集合头部开始遍历直到第一个不满足p的元素为止,所有满足p的进第一个集合,不满足p的进第二个集合。splitAt可以认为前n个元素进第一个集合,剩余元素进第二个集合。

    我们可以用下面这种方式来接收返回值:

scala> val (a,b) = x.partition(_ > 10)
a: List[Int] = List(15, 20, 12)
b: List[Int] = List(10, 5, 8)

scala> a
res23: List[Int] = List(15, 20, 12)

scala> b
res24: List[Int] = List(10, 5, 8)

    我们可以用下面的形式接收groupBy方法的返回值:

scala> val groups = x.groupBy(_ > 10)
groups: scala.collection.immutable.Map[Boolean,List[Int]] = Map(false -> List(10, 5, 8), true -> List(15, 20, 12))

scala> val trues = groups(true)
trues: List[Int] = List(15, 20, 12)

scala> val falses = groups(false)
falses: List[Int] = List(10, 5, 8)

    窗口方法sliding(w,s),w是窗口大小,s是每次滑动距离。使用这个方法,就是下标从0开始,每次向后移动s距离,每次取当前下标开始的w个元素,组成一个新的集合。

scala> val nums = (1 to 5).toArray
nums: Array[Int] = Array(1, 2, 3, 4, 5)

scala> nums.sliding(2)
res25: Iterator[Array[Int]] = non-empty iterator

scala> nums.sliding(2).toList
res26: List[Array[Int]] = List(Array(1, 2), Array(2, 3), Array(3, 4), Array(4, 5))

scala> nums.sliding(2,2).toList
res27: List[Array[Int]] = List(Array(1, 2), Array(3, 4), Array(5))

scala> nums.sliding(2,3).toList
res28: List[Array[Int]] = List(Array(1, 2), Array(4, 5))

    unzip方法处理二元祖集合,它可以把二元祖里的第一个元素归为一个集合,二元祖里的第二个元素归为第二个集合:

scala> val listOfTuple2s = List((1,2), ('a', 'b'))
listOfTuple2s: List[(AnyVal, AnyVal)] = List((1,2), (a,b))

scala> val x = listOfTuple2s.unzip
x: (List[AnyVal], List[AnyVal]) = (List(1, a),List(2, b))

    下面这个例子中,我们使用unzip方法来把couples集合中丈夫和妻子分到两个集合中:

scala> val couples = List(("Kim", "Al"), ("Julia", "Terry"))
couples: List[(String, String)] = List((Kim,Al), (Julia,Terry))

scala> val (women, men) = couples.unzip
women: List[String] = List(Kim, Julia)
men: List[String] = List(Al, Terry)

    unzip正好是zip的反方法:

scala> List(1,2,3).zip(List(4,5,6))
res30: List[(Int, Int)] = List((1,4), (2,5), (3,6))

scala> List(1,2,3).zip(List(4,5,6)).unzip
res31: (List[Int], List[Int]) = (List(1, 2, 3),List(4, 5, 6))


转载于:https://my.oschina.net/nenusoul/blog/659610

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值