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

Problem

    你想要基於一種算法或者規則,把一個序列切分爲兩個或者多個子集。
算法

Solution

    使用groupBy,partition,span,splitAt方法能夠把一個集合切分紅子集合。sliding和unzip方法也能夠用來把集合切分紅子集合,儘管sliding能夠產生許多子序列,unzip則主要用來拆分二元祖。
spa

    groupy,partition和span方法可讓你把一個集合按一個方法定義切分紅子集合,splitAt讓你按集合下標切分一個集合爲兩個子集合:scala

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的元素組成的新集合。code

    方法partition(p),span(p)和splitAt(n)會建立一個二元祖,二元祖的每一個元素都是和原集合類型相同的集合。partiton會把集合的全部元素遍歷一遍,知足條件p的元素進二元祖第一個集合,不知足條件p的元素進二元祖第二個集合。span方法會從集合頭部開始遍歷直到第一個不知足p的元素爲止,全部知足p的進第一個集合,不知足p的進第二個集合。splitAt能夠認爲前n個元素進第一個集合,剩餘元素進第二個集合。ip

    咱們能夠用下面這種方式來接收返回值:it

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方法的返回值:io

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個元素,組成一個新的集合。table

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方法處理二元祖集合,它能夠把二元祖裏的第一個元素歸爲一個集合,二元祖裏的第二個元素歸爲第二個集合:class

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集合中丈夫和妻子分到兩個集合中:List

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))
相關文章
相關標籤/搜索