Obtaining the dimension of a multidimensional array in ruby

I just started to study ruby. Now I need to find out the dimension of a multidimensional array. I looked at ruby-docs for all array methods, but could not find a method that returns a dimension.

Here is an example:

For [[1, 2],[3,4],[5,6]] size must be 2.

For [[[1,2],[2,3]],[[3,4],[5]]] dimension should be 3.

+6
source share
6 answers

There is no built-in function for this, as there may be several definitions as to what you mean by โ€œdimensionโ€ for the array. Ruby arrays can contain everything, including hashes or other arrays. Therefore, I believe that you need to implement your own function for this.

Assuming that by size you mean "the deepest nested level of arrays", this should do the trick:

 def get_dimension a return 0 if a.class != Array result = 1 a.each do |sub_a| if sub_a.class == Array dim = get_dimension(sub_a) result = dim + 1 if dim + 1 > result end end return result end 

EDIT: and since ruby โ€‹โ€‹is a great language and allows you to do some fancy things, you can also make get_dimension an Array method:

  class Array def get_dimension ... # code from above slightly modified end end 
+2
source

A simple, object oriented solution.

 class Array def depth map {|element| element.depth + 1 }.max end end class Object def depth 0 end end 
+6
source

in the simplest case

 depth = Proc.new do |array| depth = 1 while Array === array.first do array = array.first depth += 1 end depth end array = [[[1,2],[2,3]],[[3,4],[5]]] depth.call(array) #=> 3 

Or this tiny recursive method

 def depth(array, depth=1) array = array.send(:first) Array === array ? depth(array, depth+1) : depth end array = [[[1,2],[2,3]],[[3,4],[5]]] depth(array) #=> 3 
+1
source

What about:

 class Object def dimension self.class == Array ? 1 + self[0].dimension : 0 end end [[[1,2],[2,3]],[[3,4],[5]]].dimension #=> 3 
0
source

As a modification of the Tass approach:

 class Array def depth map{ |element| element.is_a?( Vector ) ? element.depth + 1 : 1 }.max end end 

Saves depth as an Array method and does not require adding a method to an Object .

Of course, this may be what you want if you are going to call my_object.depth , where you do not know in advance what my_object.class == Array

0
source

I was not happy with the other solutions, so I wrote one layer that I would use:

 def depth(array) array.to_a == array.flatten(1) ? 1 : depth(array.flatten(1)) + 1 end 

It will align the size of array 1 at a time until it can smooth out more when counting sizes.

Why is it better?

  • does not require modification for native classes (avoid if possible)
  • does not use metaprogramming ( is_a? send , respond_to? etc.)
  • pretty easy to read
  • works with hashes (notification array.to_a )
  • actually works (as opposed to checking only the first branch and other stupid things)
0
source

Source: https://habr.com/ru/post/909878/


All Articles