2014-07-04 109 views
2

我有以下数据顺序的序列:重新排序序列中斯卡拉

A, B, C, D, E, F, G, H, I, J, K, L, M, N, O 

,我需要使它看起来像这样对它进行排序:

A, F, K, B, G, L, C, H, M, D, I, N, E, J, O 

它基本上分组第一按顺序分成三组,将它们堆叠在彼此的顶部,然后读取第一列,然后下一个等,形成新的序列。

ABCDE 

FGHIJ 

KLMNO 

我有一个概念上的理解,这可能涉及到映射和压缩。我可以在命令式风格中短时间执行此操作,但我希望将其作为功能风格。

任何帮助/指针感激地收到,谢谢!

回答

8

在这里你去:

val xs = Seq('A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'I, 'J, 'K, 'L, 'M, 'N, 'O) 
val grouped = xs.grouped(5).toList 
// List(List('A, 'B, 'C, 'D, 'E), List('F, 'G, 'H, 'I, 'J), List('K, 'L, 'M, 'N, 'O)) 
val result = grouped.transpose.flatten 
// List('A, 'F, 'K, 'B, 'G, 'L, 'C, 'H, 'M, 'D, 'I, 'N, 'E, 'J, 'O) 
+0

谢谢,转矩只能在矩形矩阵上工作吗?如果输入seq只能达到'M',那么组函数会产生三个大小为5-5-3的列表? – Zuriar

+0

'.transpose'如果集合不全都具有相同的长度,则会引发异常(如果发生这种情况,您可能需要查找'.padTo')。 – Marth

+0

@ user3231690然后它将释放'IllegalArgumentException'。这是你的问题吗? –

2

任何解决方案应该在开始时grouped,其中砍下收集成片:

scala> val g = "ABCDEFGHIJKLMN".grouped(5) 
g: Iterator[String] = non-empty iterator // Will return "ABCDE", then "FGHIJ", then "KLMN" 

然后,我们把一切都成一个列表,所以我们可以很容易地拿尾巴:

scala> val l = g.map(_.toList).toList 
List[List[Char]] = List(List(A, B, C, D, E), List(F, G, H, I, J), 
         List(K, L, M, N)) 

现在我们通过采取连续的尾巴收集这些,停止时没有什么留下的:

scala> val i = Iterator.iterate(l)(_.map(_ drop 1).filter(_.nonEmpty)).takeWhile(_.nonEmpty) 
i: Iterator[List[List[Char]]] = non-empty iterator 
// List(List(A, B, C, D, E), List(F, G, H, I, J), List(K, L, M, N)) 
// List(List(B, C, D, E), List(G, H, I, J), List(L, M, N)) 
// List(List(C, D, E), List(H, I, J), List(M, N)) 
// List(List(D, E), List(I, J), List(N)) 
// List(List(E), List(J)) 

这看起来大,但由于我们使用List,短名单共享与较长的内存,所以它不是一个可怕的?在大小(N^2)爆炸。但是,我们真的只是想的头上,我们已经过滤掉一切空的,所以我们就可以做到这一点:

scala> val h = i.map(_.map(_.head)) 
h: Iterator[List[Char]] = non-empty iterator 
// List(A, F, K) 
// List(B, G, L) 
// List(C, H, M) 
// List(D, I, N) 
// List(E, J) 

终于从一个迭代器转换为严格的收集和扁平化:

scala> val ans = h.toList.flatten 
ans: List[Char] = List(A, F, K, B, G, L, C, H, M, D, I, N, E, J) 

(如果您想要返回String,请添加mkString)。

请注意,临时变量仅用于解释清楚。如果你想把它全部写在一行上,你可以。 (这会是一个相当长的线。)

(另请注意,如果您例如打印出的迭代器,它们会消耗掉。)

这是在一个大的一举:

("ABCDEFGHIJKLMN".grouped(5).map(_.toList).toList match { 
    case l => Iterator.iterate(l)(_.map(_ drop 1).filter(_.nonEmpty)).takeWhile(_.nonEmpty) 
}).map(_.map(_.head)).toList.flatten 

但这是非常不透明的,所以把东西传播出去留出评论空间是一个好主意。