我有一个字符串列表,它采用以下形式:
000000
011220
011220
033440
033440
000000
我希望将这些字符串转换为表示每个2x2块的值列表,同时保留行信息。表示每个2x2块的数据是否存储在列表或元组中是无关紧要的。例如,表示左上角的2x2块可以采用以下形式之一:
(0, 0, 0, 1)
List((0, 0), (0, 1))
List(0, 0, 0, 1)
List(List(0, 0), List(0, 1))
下面的Scala代码执行规定的转换,但它似乎过于复杂。我可以将一些功能分解为单独的函数,但是我无法看到如何将此代码转换为更简单的形式,如for-comprehension。
注意:为简洁起见,我简化了值列表。
scala> val data = List("000000", "011220", "033440")
data: List[String] = List(000000, 011220, 033440)
scala> val values = (data map { _.toList.sliding(2).toList } sliding(2) map { _.transpose } map { _ map { _.flatten } }).toList
values: List[List[List[Char]]] = List(List(List(0, 0, 0, 1), List(0, 0, 1, 1), List(0, 0, 1, 2), List(0, 0, 2, 2), List(0, 0, 2, 0)), List(List(0, 1, 0, 3), List(1, 1, 3, 3), List(1, 2, 3, 4), List(2, 2, 4, 4), List(2, 0, 4, 0)))
为清楚起见,我已经将一些列表重新标记为' Row'和' Block',但它们不代表任何具体的类。他们只是简单的绰号,可以对上面的输出提供更有意义的观点。
values: List[Row[Block[Char]]] = List(Row(Block(0, 0, 0, 1), Block(0, 0, 1, 1), ...), Row(Block(0, 1, 0, 3), Block(1, 1, 3, 3), ...))
我对Scala相对较新,我想知道上面代码是否是实现此转换的好方法,还是有更优雅的方式?
答案 0 :(得分:2)
你可以这样做(.toList
基本上是在这里查看结果而不是non-empty iterator
):
scala> val values = data.map(_.sliding(2).toList) // create a sliding window over consecutive characters
.sliding(2).toList // slide over consecutive rows
.flatMap { case List(row1, row2) => row1 zip row2 } // zip rows together, creating the blocks
values: List[(String, String)] = List((00,01), (00,11), (00,12), (00,22),
(00,20), (01,03), (11,33), (12,34),
(22,44), (20,40))
答案 1 :(得分:0)
这是使用for-comprehension完成任务的一种方法。
(for {
// Create the pair of strings for each 'row'. For example: List(011220, 033440)
List(row1, row2) <- data.sliding(2)
} yield (
for {
// Create the sequence of values representing a block.
Seq((a1, a2),(b1, b2)) <- row1 zip row2 sliding(2)
} yield (a1, b1, a2, b2) ).toVector
).toList
为清楚起见,每个2x2块是一个元组,每行是一个Vector,整个行集是一个List。 REPL中的结果如下:
scala> val data = List("000000", "011220", "033440")
data: List[String] = List(000000, 011220, 033440)
scala> (for { List(row1, row2) <- data.sliding(2) } yield (for { Seq((a1, a2),(b1, b2)) <- row1 zip row2 sliding(2) } yield (a1, b1, a2, b2) ).toVector ).toList
res1: List[Vector[(Char, Char, Char, Char)]] = List(Vector((0,0,0,1), (0,0,1,1), (0,0,1,2), (0,0,2,2), (0,0,2,0)), Vector((0,1,0,3), (1,1,3,3), (1,2,3,4), (2,2,4,4), (2,0,4,0)))