2

Suppose I have an array of strings in Scala:

val strings = Array[String]("1", "2", "3", "4", "5", "6", "7")

What I need is to make a new array which elements will be obtained as a concatenation of each three (any number) consequent elements of the first array, which should result in ("123", "456", "7")

Being new to Scala I wrote the following code which was neither concise nor effective:

var step = 3
val strings = Array[String]("1", "2", "3", "4", "5", "6", "7")
val newStrings = collection.mutable.ArrayBuffer.empty[String]

for (i <- 0 until strings.length by step) {
  var elem = ""
  for (k <- 0 until step if i + k < strings.length) {
    elem += strings(i + k)
  }
  newStrings += elem
}

What would be the Scala way for doing this?

user unknown
  • 35,537
  • 11
  • 75
  • 121
nab
  • 4,751
  • 4
  • 31
  • 42

3 Answers3

9
strings.grouped(3).map(_.mkString).toArray

or

strings grouped 3 map (_.mkString) toArray

I personally prefer the first version :)

Rogach
  • 26,050
  • 21
  • 93
  • 172
4
strings grouped 3 map (_.mkString)

or (in order to really get an Array back)

(strings grouped 3 map (_.mkString)).toArray
Debilski
  • 66,976
  • 12
  • 110
  • 133
  • Yeah,your version is dot-free :) But you'll need an .toArray statement - your version returns an Iterator instead of Array. – Rogach May 12 '12 at 12:16
  • Yeah, but I didn’t want to wrap the whole statement in parentheses just for that. :) – Debilski May 12 '12 at 12:20
  • 3
    Fwiw: http://stackoverflow.com/questions/10233227/scala-infix-vs-dot-notation/10313469#10313469. – missingfaktor May 12 '12 at 12:21
  • You don't need to wrap it :) It allows one trailing call. – Rogach May 12 '12 at 12:22
  • @Rogach: Now. But who knows what the future brings. http://docs.scala-lang.org/sips/pending/modularizing-language-features.html – Debilski May 12 '12 at 12:25
  • @Rogach, also you need to add a semicolon after that, or else it may cause issues like [this](http://stackoverflow.com/questions/2246212/why-does-scalas-semicolon-inference-fail-here). – missingfaktor May 12 '12 at 13:55
  • 2
    And our Scala starts looking like Lisp with extra parentheses :/ – Luigi Plinge May 12 '12 at 15:17
3

... or use sliding

val strings = Array[String]("1", "2", "3", "4", "5", "6", "7")
strings.sliding (3, 3) .map (_.mkString).toArray

res19: Array[String] = Array(123, 456, 7)

Sliding: You take 3, and move forward 3. Variants:

scala> strings.sliding (3, 2) .map (_.mkString).toArray
res20: Array[String] = Array(123, 345, 567)

take 3, but forward 2

scala> strings.sliding (2, 3) .map (_.mkString).toArray
res21: Array[String] = Array(12, 45, 7)

take 2, forward 3 (thereby skipping every third)

user unknown
  • 35,537
  • 11
  • 75
  • 121