这是一个非常简单的解决方案:
def splitAlt[T](s: Seq[T]): (Seq[T],Seq[T]) = {
val (fsts,snds) = s.zipWithIndex.partition { case (x,i) => i % 2 == 0 }
(fsts.map(_._1),snds.map(_._1))
}
splitAlt("") // -> (Seq(),Seq())
splitAlt("a") // -> (Seq(a),Seq())
splitAlt("ab") // -> (Seq(a),Seq(b))
splitAlt("abc") // -> (Seq(a,c),Seq(b))
splitAlt("abcd") // -> (Seq(a,Seq(b,d))
splitAlt("abcde") // -> (Seq(a,c,e),d))
我声称它很优雅,因为:
- 它不会引发异常,它只会返回空序列;
- 它适用于任何类型的序列,而不仅仅是字符;
- 它适用于任何长度的序列;
- 它仅遍历序列一次。
更新:这是对任意数量的组的概括:
def splitGen[T](xs: Seq[T],n: Int): Seq[Seq[T]] = {
val groups =
xs.zipWithIndex
.groupBy { case (x,i) => i % n }
.mapValues { vs => vs.map(_._1) }
0 until n map groups
}
splitGen("abcdefg",1) // -> Seq(Seq(a,b,d,e,f,g))
splitGen("abcdefg",2) // -> Seq(Seq(a,g),f))
splitGen("abcdefg",3) // -> Seq(Seq(a,Seq(c,4) // -> Seq(Seq(a,f),Seq(d))
splitGen("abcdefg",5) // -> Seq(Seq(a,Seq(c),Seq(d),Seq(e))
您可以通过将原始序列填充为正确的长度,然后对结果进行填充,来概括grouped
+ transpose
解决方案,但这需要您注意一些特殊情况:
def splitGen[T](xs: Seq[T],n: Int): Seq[Seq[T]] = {
/* Pad */
val paddedLength: Int = math.ceil(xs.length / n.toDouble).toInt * n
val padded: Seq[T] =
if (xs.isEmpty) xs
else xs.padTo(paddedLength,xs.head)
/* Transpose */
val transposed = padded.grouped(n).toList.transpose
/* Unpad */
if (paddedLength == xs.length) transposed
else transposed.zipWithIndex.map { case (row,i) =>
if (i < xs.length % n) row
else row.init
}
}
,
这是一种基于grouped
+ transpose
解决方案的方法。
def splitAlt[T](s: Seq[T]) = {
s.grouped(2).toList.map(p => Seq(p.headOption,p.tail.headOption)).transpose.map(_.flatten)
}
基本上,它将List[T]
返回的内部grouped
转换为具有两个元素的List[Option[T]]
,因为transpose
要求所有集合的大小都相等。
请注意,这将返回嵌套列表,而不是一对列表。如果要将结果转换为元组,我们需要特别注意少于2个元素的情况,因此为了“优雅”,我将其保留为这样。
本文链接:https://www.f2er.com/3058302.html