agusgambina
agusgambina

Reputation: 6689

Scala group elements in grids

I am trying group elements of a sequence in grids. I have 81 elements.

|  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |
|  9  | 10  | 11  | 12  | 13  | 14  | 15  | 16  | 17  |
| 18  | 19  | 20  | 21  | 22  | 23  | 24  | 25  | 26  |
| 27  | 28  | 29  | 30  | 31  | 32  | 33  | 34  | 35  |
| 36  | 37  | 38  | 39  | 40  | 41  | 42  | 43  | 44  |
| 45  | 46  | 47  | 48  | 49  | 50  | 51  | 52  | 53  |
| 54  | 55  | 56  | 57  | 58  | 59  | 60  | 61  | 62  |
| 63  | 64  | 65  | 66  | 67  | 68  | 69  | 70  | 71  |
| 72  | 73  | 74  | 75  | 76  | 77  | 78  | 79  | 80  |

I want to group them in grids of 3x3 like this

|  0  |  1  |  2  |
|  9  | 10  | 11  |
| 18  | 19  | 20  |

I am testing with this, I have an input

val input = "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80"

then I parse that input

val parsed = input.split(",").toList.map { x => x.trim }

then I group elements

val groups = parsed.grouped(3).toList

If execute the following line I get the first column of grids

val grids1 = groups.sliding(1,3).toList.grouped(3).toList.flatten.flatten.grouped(3).toList

However I can not realize how can I get the other columns

Upvotes: 1

Views: 116

Answers (3)

curious
curious

Reputation: 2928

This can easily be done by using sliding function on List

scala> input.sliding(9, 9).map(_.sliding(3,3).toList).foreach(println)
List(List(0, 1, 2), List(3, 4, 5), List(6, 7, 8))
List(List(9, 10, 11), List(12, 13, 14), List(15, 16, 17))
List(List(18, 19, 20), List(21, 22, 23), List(24, 25, 26))
List(List(27, 28, 29), List(30, 31, 32), List(33, 34, 35))
List(List(36, 37, 38), List(39, 40, 41), List(42, 43, 44))
List(List(45, 46, 47), List(48, 49, 50), List(51, 52, 53))
List(List(54, 55, 56), List(57, 58, 59), List(60, 61, 62))
List(List(63, 64, 65), List(66, 67, 68), List(69, 70, 71))
List(List(72, 73, 74), List(75, 76, 77), List(78, 79, 80))

Upvotes: 0

Xavier Guihot
Xavier Guihot

Reputation: 61716

Assuming you have this List in input:

val input = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80)

then you could perform:

input.zipWithIndex
  .map { case (d, i) => (i % 9 / 3, i / 27, d) } // 28 => (0, 1, 28)
  .groupBy { case (x, y, d) => (x, y) }
  .map { case ((x, y), values) => values.map(_._3) }

which returns:

List(List(54, 55, 56, 63, 64, 65, 72, 73, 74), List(0, 1, 2, 9, 10, 11, 18, 19, 20), List(6, 7, 8, 15, 16, 17, 24, 25, 26), List(30, 31, 32, 39, 40, 41, 48, 49, 50), List(60, 61, 62, 69, 70, 71, 78, 79, 80), List(27, 28, 29, 36, 37, 38, 45, 46, 47), List(57, 58, 59, 66, 67, 68, 75, 76, 77), List(33, 34, 35, 42, 43, 44, 51, 52, 53), List(3, 4, 5, 12, 13, 14, 21, 22, 23))

Details of each step of the pipeline:

  • zipWithIndex in order to get the index of each element (in case the element is different from the index)
  • for each element, prepare its clustering by getting (via modulos and integer divisions) its "main column" (columns 0 to 2 become main column 1, columns 3 to 5 become main column 2, ...) using i % 9 / 3 (for instance 39 % 9 / 3 = 1) and same thing for "main rows" using i / 27 (39 / 27 = 1).
  • Each element is then gouped by "main column/row" (x, y) using groupBy.
  • And finally we get rid of the "main columns/rows" (x, y) information to only keep values with a final map.

Not sure which order is desired, but you could use a final sortBy.

Upvotes: 1

Raman Mishra
Raman Mishra

Reputation: 2686

object solution extends App{

  val input = "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, " +
    "28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55," +
    " 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80"

  val inputList = input.split(",").toList.grouped(9).toList
.map(_.grouped(3).toList)
.transpose.flatMap(_.grouped(3).toList)

inputList.foreach(println)
}

I think you were looking for this.

//output:

    List(List(List(0,  1,  2), List( 9,  10,  11), List( 18,  19,  20)), List(List( 27,  28,  29), List( 36,  37,  38), List( 45,  46,  47)), List(List( 54,  55,  56), List( 63,  64,  65), List( 72,  73,  74)))
List(List(List( 3,  4,  5), List( 12,  13,  14), List( 21,  22,  23)), List(List( 30,  31,  32), List( 39,  40,  41), List( 48,  49,  50)), List(List( 57,  58,  59), List( 66,  67,  68), List( 75,  76,  77)))
List(List(List( 6,  7,  8), List( 15,  16,  17), List( 24,  25,  26)), List(List( 33,  34,  35), List( 42,  43,  44), List( 51,  52,  53)), List(List( 60,  61,  62), List( 69,  70,  71), List( 78,  79,  80)))

if you want your output like this:

List(0,  1,  2,  9,  10,  11,  18,  19,  20)
List( 27,  28,  29,  36,  37,  38,  45,  46,  47)
List( 54,  55,  56,  63,  64,  65,  72,  73,  74)
List( 3,  4,  5,  12,  13,  14,  21,  22,  23)
List( 30,  31,  32,  39,  40,  41,  48,  49,  50)
List( 57,  58,  59,  66,  67,  68,  75,  76,  77)
List( 6,  7,  8,  15,  16,  17,  24,  25,  26)
List( 33,  34,  35,  42,  43,  44,  51,  52,  53)
List( 60,  61,  62,  69,  70,  71,  78,  79,  80)

you can use:

inputList.map(_.flatten).foreach(println)

Upvotes: 1

Related Questions