2015-06-03 4 views
2

Я искал многомерные массивы в Scala и наткнулся на несколько простых способов создания многомерных массивов. А именно:6- или более размерные массивы в Scala

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

Или даже

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

Однако это работает только для 1 - 5 мерных массивов:

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

Так как люди обычно имеют дело с созданием более высокоразмерные массивы? Остается ли это для сторонних библиотек для реализации или существуют другие структуры данных, которые Scala поощряет нас использовать вместо массивов с большими размерами?

+0

Для чего нужен 6-мерный массив? Это не то, что людям нужно регулярно. – Jesper

+0

У меня на самом деле не было конкретного случая использования - я просто интересовался полнотой, в случае возникновения проблемы. –

ответ

2

Если вы действительно хотите произвольное количество измерений, вы, как правило, используете один плоский массив со вторым массивом, который индексирует по размеру, чтобы добраться до нужного элемента. Так, например,

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 
    } 
} 

было бы началом. Существуют различные библиотеки математики, которые делают такие вещи ( IIRC Apache Commons Math делает Я не могу быстро найти библиотеку математики Java, которая делает это, но ImgLib2 использует аналогичные методы для данных изображения (они также выполняют локальную разбивку)). Это не очень полезная вещь, поэтому вы, как правило, находите ее в библиотеках математики.

+0

Я не получу последнее предложение. Я также считаю, что плоские массивы очень полезны. Вы можете уточнить? – ziggystar

+0

@ziggystar - Упаковка в плоские массивы наиболее полезна при попытке выполнить произвольную математику произвольной размерности. Для общих нематематических алгоритмов, если вам нужны несколько измерений, нет оснований не иметь реальных массивов массивов. –

+0

Хорошо, понял, что вы имеете в виду. Я проверил Commons Math и не смог найти реализацию многомерного массива, можете ли вы подтвердить? – ziggystar

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

Array.ofDim реализация использует этот образец. см. https://github.com/scala/scala/blob/v2.11.6/src/library/scala/Array.scala#L216-234

+0

Спасибо за ответ! Это снова работает для небольших (6 или 7 или около того) размеров, но, скажем, для 30 измерений, разве это не громоздко? 'Array.tabulate (3) (_ => Array.tabulate (3) (_ => Array.tabulate (3) => .....' –

+0

@JoshLemer Похож на '@ tailrec' - ваш друг – Daenyth

+0

@ Daenyth Я просто играл с рекурсивной реализацией игрушек, но не уверен, что это возможно, поскольку каждый рекурсивный вызов возвращает другой тип. Например, '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: _ *)) ' .. Кажется, что не работает на каждом уровне рекурсии, возвращается другой тип (Array [Array [Int]]], Array [Array [Int]] или Array [Int] и т. Д.), так что нет способа правильно определить тип возврата? –

Смежные вопросы