Dimensions of a collection, and how to traverse it in an efficient, elegant manner
I'm trying to find an elegant way to deal with multi-dimensional collections in Scala. My understanding is that I can have up to a 5 dimensional collection using tabulate, such as in the case of the following 2-Dimensional array:
val test = Array.tabulate[Double](row,col)(_+_)
and that I can access the elements of the array using
for(i<-0 until row) {
for(j<-0 until col) {
test(i)(j) = 0.0
}
}
If I don't know a priori what I'm going to be handling, what might be a succinct way of determining the structure of the collection, and spanning it, without doing something like:
case(Array(x)) =>
for(i<-1 until dim1) {
test(i) = 0.0
}
case(Array(x,y)) =>
for(i<-1 until dim1) {
for(j<-1 until dim2) {
test(i开发者_StackOverflow中文版)(j) = 0.0
}
}
case(Array(x,y,z)) =>
...
The dimensional values n1, n2, n3, etc... are private, right? Also, would one use the same trick of unwrapping a 2-D array into a 1-D vector when dealing with n-Dimensional objects if I want a single case to handle the traversal?
Thanks in advance
Bruce
i would use recursion and pattern matching in this case:
def doSome(a:Array[_]){
for(i <- a){
i match{
case x:Array[_] => doSome(x)
case x => println(x) // do something sensible here
}
}
}
First, some corrections:
val test = Array.tabulate[Double](row,col)(_+_)
This will produce an Array[Array[Double]]
, and the easiest way to zero every element is:
test foreach { inner => in.indices foreach { _ => 0.0 } }
Where you loop over each inner array contained by the outer array, and for the inner array update each element. There's no need to know the actual number of elements, nor is it desirable to do so (just imagine doing that with a parallel array!)
It would be much easier to use map
, and work with the array as though it were immutable, but that seems to go against the spirit of your original request, so moving swiftly on...
As well as misunderstanding the nature of multi-dimensional arrays returned from the tabulate function (e.g. a nested array of arrays). You're also using pattern matching as though it were a Java switch statement, this isn't quite right. To match arrays of varying dimensionality, you'd want something like this:
case Array[Double] => ...
case Array[Array[Double]] => ...
But I'd advise against that approach. It wouldn't be easy to express safely in the type system, and you already know exactly what type was returned from tabulate based on the number of arguments you supplied
精彩评论