6

What's the recommended way of creating a pre-populated two-dimensional array in Scala? I've got the following code:

val map = for {
    x <- (1 to size).toList
} yield for {
        y <- (1 to size).toList
    } yield (x, y)

How do I make an array instead of list? Replacing .toList with .toArray doesn't compile. And is there a more concise or readable way of doing this than the nested for expressions?

Eugene Yokota
  • 94,654
  • 45
  • 215
  • 319
asteinlein
  • 63
  • 1
  • 3

2 Answers2

8

On Scala 2.7, use Array.range:

for {
  x <- Array.range(1, 3)
} yield for {
  y <- Array.range(1, 3)
} yield (x, y)

On Scala 2.8, use Array.tabulate:

Array.tabulate(3,3)((x, y) => (x, y))
Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
  • Array.tabulate seems sweet, and looks like Array.fromFunction suggested by Rex Kerr in another answer. What's the difference (apart from the fact that I see Array.fromFunction is deprecated in 2.8)? And how do they actually work? – asteinlein Mar 23 '10 at 18:05
  • @asteinlein I'm not sure about `fromFunction` -- I had never noticed it before -- but `tabulate` (which is present on `List` on Scala 2.7) works pretty much like the for-comprehension you wrote, but `0 until size` instead of `1 to size`. On Scala 2.7, however, it is one-dimensional only, so you'd need to nest them. On Scala 2.8, you can provide multiple dimensions (up to 5, I think). – Daniel C. Sobral Mar 24 '10 at 01:38
  • Thanks. For anyone else interested, this works nicely on 2.7: List.tabulate(3, x => List.tabulate(3, y => (x, y)).toArray).toArray – asteinlein Mar 24 '10 at 18:34
  • Another straightforward way... val 2d_array:Array[Array[MyClass]] = Array.fill(height) { Array.fill(width) { new MyClass } } – jk. Feb 16 '13 at 21:03
  • @jk. If you think that's the same thing, you didn't understand what this is doing. – Daniel C. Sobral Feb 16 '13 at 22:46
  • ah, i missed the requirement to pass the coordinates into the function that generates the array maybe? – jk. Feb 16 '13 at 22:52
2

Among other ways, you can use use Array.range and map:

scala> Array.range(0,3).map(i => Array.range(0,3).map(j => (i,j)))
res0: Array[Array[(Int, Int)]] = Array(Array((0,0), (0,1), (0,2)), Array((1,0), (1,1), (1,2)), Array((2,0), (2,1), (2,2)))

Or you can use Array.fromFunction:

scala> Array.fromFunction((i,j) => (i,j))(3,3)                    
res1: Array[Array[(Int, Int)]] = Array(Array((0,0), (0,1), (0,2)), Array((1,0), (1,1), (1,2)), Array((2,0), (2,1), (2,2)))

Scala 2.8 gives you even more options--look through the Array object. (Actually, that's good advice for 2.7, also....)

Rex Kerr
  • 166,841
  • 26
  • 322
  • 407