我想将大小> 2的序列分成这样的交替序列:
I would like to split a sequence of size > 2 into alternating sequences like this:
def splitAlt(s: Seq[Char]): (Seq[Char], Seq[Char]) = ??? splitAlt(Nil) // raise an exception splitAlt("a") // raise an exception splitAlt("ab") // (Seq('a'), Seq('b')) splitAlt("abc") // (Seq('a', 'c'), Seq('b'))我找到了一个优雅的解决方案,其中 grouped 和 transpose 我想使用.不幸的是,它仅在输入序列具有偶数大小的情况下才起作用.您将如何修改该解决方案以适用于任何大小的输入?
I found an elegant solution with grouped and transpose I'd like to use. Unfortunately it works only i fthe input sequence has even size. How would you modify that solution to work for input of any size ?
您有更优雅的解决方案吗?
Do you have a more elegant solution ?
推荐答案这是一个非常简单的解决方案:
This is a very straightforward solution:
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, c), Seq(b, d)) splitAlt("abcde") // -> (Seq(a, c, e), Seq(b, d))我声称它很优雅,因为:
I claim it's elegant because:
- 它不会引发异常,它只会返回空序列;
- 它适用于任何类型的序列,而不仅仅是字符;
- 它适用于任何长度的序列;
- 它仅遍历一次序列.
更新:这是任意数量的组的概括:
Update: this is a generalization for an arbitrary number of groups:
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, c, d, e, f, g)) splitGen("abcdefg", 2) // -> Seq(Seq(a, c, e, g), Seq(b, d, f)) splitGen("abcdefg", 3) // -> Seq(Seq(a, d, g), Seq(b, e), Seq(c, f)) splitGen("abcdefg", 4) // -> Seq(Seq(a, e), Seq(b, f), Seq(c, g), Seq(d)) splitGen("abcdefg", 5) // -> Seq(Seq(a, f), Seq(b, g), Seq(c), Seq(d), Seq(e))您可以通过将原始序列填充为正确的长度,然后取消填充结果,来概括 grouped + transpose 解决方案,但这需要您注意一些特殊情况:
You can generalize the grouped+transpose solution by padding the original sequence for the length to be just right and then unpadding the result, but it requires you to take care of some special cases:
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 }}
更多推荐
将一个序列分成两个交替的序列
发布评论