如何在Scala中将字符串列表转换为另一种形式?

时间:2015-07-14 15:31:51

标签: scala

我有一个字符串列表,它采用以下形式:

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相对较新,我想知道上面代码是否是实现此转换的好方法,还是有更优雅的方式?

2 个答案:

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