DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

Extracting All Subarray Indices From A Multi-dimensional Array

04.22.2006
| 4054 views |
  • submit to reddit
        Note the use of Array#fetch to define return values for missing indices!
Example: ar = []; x = ar.fetch(5, [])  returns an empty array for non-existing index 5.



class Array

   def subar_indices(ar=[], temp=[])
      temp = temp.dup
      self.each_with_index { |item, index| 
         if item.class == Array
            temp << index
            ar << temp
            ar = item.subar_indices(ar, temp)
         end
      }
      ar.uniq
   end


   def extract_subar_indices
      subarray_indices = self.subar_indices  # subarray_indices is a two-dimensional array
      # puts subarray_indices.inspect
      
      return subarray_indices if subarray_indices.empty?

      first_subar = subarray_indices.shift   # the first subarray contains all two-dimensional subarray indices                

      subarray_indices.each do |subar|
         subar_size = subar.size
         str = ""
         count = -1
         (subar_size - 1).times { count += 1; str << ".fetch(subar[#{count}], [])" }
         str << ".fetch(subar[#{count + 1}], {}"
         str = "self" << str
         if eval(str).class == Hash then subar.shift; redo end
      end

      first_subar.reverse.each do |item| subarray_indices.unshift([item]) end
      subarray_indices
   end

end


array = [1, 2, [3, 4, [5, 6]], 7, 8, [9]]

indices = array.extract_subar_indices

puts indices.inspect  # [[2], [5], [2, 2]]


    

Comments

Snippets Manager replied on Sun, 2006/01/29 - 5:07pm

Just for completion, here's a way to do it: indices = array.extract_subar_indices # for array in main snippet above indices = indices.sort_by { |subar| subar.size }.reverse indices.each do |subar_index| subar_index_size = subar_index.size str = "" (subar_index_size).times { |x| str << "[subar_index[#{x}]]" } str = "array" << str eval(str) << "new item" # eval(str) is subarray if eval(str).include?(3) && eval(str).size > 2 eval(str).reverse! eval(str).unshift("unshifted item") eval(str).sort_by { |item| item.size } eval(str).replace(["replaced subarray"]) end end puts array.inspect # [1, 2 ["replaced subarray], 7, 8, [9, "new item]]

Snippets Manager replied on Sun, 2006/01/29 - 5:07pm

Well, obviously, it's a way to add items to any subarray without any prior knowledge of subarray indices (... or Subarray#replace, sort, reverse, ...).

Snippets Manager replied on Mon, 2012/05/07 - 2:23pm

I'm seeing a theme, but.. why do you want to do this? Just curious!