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))