2

I was looking into multi-dimensional Arrays in Scala and came across some easy ways to create multi-dimensional Arrays. Namely:

val my3DimensionalArray = Array.ofDim[Int](3,4,5) //array with dimensions 3 x 4 x 5

Or even

val myFilledArray = Array.fill[Int](3,4,5)(0) //Array of same dimension filled with 0's

However this only works for 1 - 5 dimensional Arrays:

val my6DimensionalArray = Array.ofDim[Int](3,3,3,3,3,3) //Error

So how do people usually deal with creating higher dimensinoal Arrays? Is this left to 3rd party libraries to implement, or are there other data structures that Scala encourages us to use instead of high dimensional Arrays?

Josh Lemer
  • 446
  • 3
  • 18
  • What do you need a 6-dimensional array for? This is not something that people need regularly. – Jesper Jun 03 '15 at 14:34
  • 1
    I didn't actually have a particular use-case in mind - I was just wondering for completeness, in case the issue comes up. – Josh Lemer Jun 03 '15 at 14:38

2 Answers2

3
// create array of 5-dim-array => 6 dim array
Array.tabulate(3)(_ => Array.ofDim[Int](3,3,3,3,3)) 

Array.ofDim implementation uses this this pattern. see https://github.com/scala/scala/blob/v2.11.6/src/library/scala/Array.scala#L216-234

planetenkiller
  • 729
  • 5
  • 15
  • Thanks for the answer! This works again for small (6 or 7 or so) dimensions, but for say 30 dimensions, wouldn't this be unwieldy? `Array.tabulate(3)(_ => Array.tabulate(3)(_ => Array.tabulate(3) => .....` – Josh Lemer Jun 03 '15 at 15:22
  • @JoshLemer Sounds like `@tailrec` is your friend – Daenyth Jun 03 '15 at 15:27
  • @Daenyth I actually was just playing around with making a toy recursive implementation, but not sure it's possible, since each recursive call returns a different type. For instance `def highDimArray(n: Int*) = if(n.length == 5) Array.ofDim[Int](n(0),n(1), ... , n(4) ) else Array.tabulate(n.head)(_ => highDimArray(n.tail: _*))` ..doesn't seem work as at each level of recursion, a different type is returned (Array[Array[Int]]], Array[Array[Int]] or Array[Int] etc.), so there's no way to define the return type right? – Josh Lemer Jun 03 '15 at 15:40
  • You need a type that's self recursive like `Free` or maybe `List` – Daenyth Jun 03 '15 at 16:07
  • 3
    I think the need for 30-dimensional arrays is sufficiently rare that it really doesn't matter that it's unweildy. I can't think of a use-case that uses that many dimensions without basically being a bad emulation of a tree/graph. – The Archetypal Paul Jun 03 '15 at 16:27
2

If you really want arbitrary numbers of dimensions, you typically use a single flat array with a second array that indexes by dimension to get to the element you want. So, for instance,

class MultiArray(dims: Array[Int]) {
  private val array = new Array[Double](dims.product)
  private def arrayIndex(index: Array[Int]) = {
    var i = index.length - 1
    var k = index(i)
    var n = 1
    while (i > 0) {
      n *= dims(i)
      k += n * index(i-1)
      i -= 1
    }
    k
  }
  def apply(index: Array[Int]) = array(arrayIndex(index))
  def update(index: Array[Int], value: Double) {
    array(arrayIndex(index)) = value
  }
}

would be a start. There are various mathematics libraries that do this sort of thing (IIRC Apache Commons Math does I can't quickly find a Java mathematics library that does, but ImgLib2 uses similar techniques for image data (they do local chunking also)). It's not really a generally useful thing to do, which is why you tend to find it in maths libraries.

Rex Kerr
  • 166,841
  • 26
  • 322
  • 407
  • I don't get your last sentence. I also find flat arrays very useful. Can you clarify? – ziggystar Jul 28 '15 at 07:50
  • @ziggystar - Packing into flat arrays is most useful when trying to do fast arbitrary-dimension mathematics. For general non-mathematical algorithms, if you need multiple dimensions there's little reason not to have actual arrays of arrays. – Rex Kerr Jul 28 '15 at 18:55
  • Ok, got what you mean. I checked Commons Math and couldn't find a multi-dim array implementation, can you confirm? – ziggystar Jul 29 '15 at 07:20
  • @ziggystar - Hm, you're right. I was thinking of C++ libraries, maybe? None of the Java libraries I checked do this. – Rex Kerr Jul 29 '15 at 18:39