# class Array

### Public Class Methods

gxg_import(the_exported_record=nil) click to toggle source

    # File lib/gxg/gxg_augmented.rb, line 3997
    def self.gxg_import(the_exported_record=nil)
      result = nil
      if the_exported_record.is_a?(Hash)
        if the_exported_record[:type] == "Hash"
          result = ::Hash::gxg_import(the_exported_record)
        else
          import_value = Proc.new do |type,value|
            if value.is_a?(String)
              begin
                the_class = eval(type)
                if the_class.respond_to?(:parse)
                  value = the_class.parse(value)
                else
                  if the_class.respond_to?(:new)
                    value = the_class.new(value)
                  else
                    if the_class.respond_to?(:try_convert)
                      value = the_class.try_convert(value)
                    end
                  end
                end
              rescue Exception => the_error
              end
            end
            value
          end
          if the_exported_record[:type] == "Array"
            result = []
            import_db = [{:parent => nil, :parent_selector => nil, :object => result, :record => the_exported_record}]
            while import_db.size > 0 do
              entry = import_db.shift
              if entry[:record][:content].is_a?(Hash)
                entry[:record][:content].each_pair do |selector, value|
                  if value[:type] == "Hash"
                    entry[:object][(selector)] = {}
                    import_db << {:parent => entry[:object], :parent_selector => selector, :object => entry[:object][(selector)], :record => value}
                  else
                    if value[:type] == "Array"
                      entry[:object][(selector)] = []
                      import_db << {:parent => entry[:object], :parent_selector => selector, :object => entry[:object][(selector)], :record => value}
                    else
                      entry[:object][(selector)] = import_value.call(value[:type], value[:content])
                    end
                  end
                end
              else
                if entry[:record][:content].is_a?(Array)
                  entry[:record][:content].each_with_index do |value, selector|
                    if value[:type] == "Hash"
                      entry[:object][(selector)] = {}
                      import_db << {:parent => entry[:object], :parent_selector => selector, :object => entry[:object][(selector)], :record => value}
                    else
                      if value[:type] == "Array"
                        entry[:object][(selector)] = []
                        import_db << {:parent => entry[:object], :parent_selector => selector, :object => entry[:object][(selector)], :record => value}
                      else
                        entry[:object][(selector)] = import_value.call(value[:type], value[:content])
                      end
                    end
                  end
                end
              end
            end
          else
            result = import_value.call(the_exported_record[:type], the_exported_record[:content])
          end
        end
      end
      result
    end

process(the_array=[],&block) click to toggle source

Interesting research on extending ruby classes '|' for instance: verboselogging.com/2011/05/06/simple-ruby-pipes Also: stackoverflow.com/questions/4234119/ruby-pipes-how-do-i-tie-the-output-of-two-subprocesses-together And a really nice one: jstorimer.com/2012/03/18/a-unix-shell-in-ruby-pipes.html#Shell%20Pipelines%20Demystified

    # File lib/gxg/gxg_augmented.rb, line 3704
    def self.process(the_array=[],&block)
      new_array = []
      if block.respond_to?(:call)
        if the_array.is_any?(::Array, ::Hash, ::GxG::ByteArray, ::Struct, ::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
          new_array = the_array.process(&block)
        else
          raise ArgumentError, "you must pass a Array, a Hash, or a ByteArray"
        end
      end
      new_array
    end

search(the_array=[],&block) click to toggle source

    # File lib/gxg/gxg_augmented.rb, line 3716
    def self.search(the_array=[],&block)
      new_array = []
      if block.respond_to?(:call)
        if the_array.is_any?(::Array, ::Hash, ::GxG::ByteArray, ::Struct, ::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
          new_array = the_array.search(&block)
        else
          raise ArgumentError, "you must pass a Array, a Hash, or a ByteArray"
        end
      end
      new_array
    end

### Public Instance Methods

average() click to toggle source

    # File lib/gxg/gxg_augmented.rb, line 4068
    def average()
      # See: https://stackoverflow.com/questions/1341271/how-do-i-create-an-average-from-a-ruby-array
      self.instance_eval { reduce(:+).to_f / size.to_f }
    end

get_at_path(the_path="/") click to toggle source

    # File lib/gxg/gxg_augmented.rb, line 3880
    def get_at_path(the_path="/")
      # /^(?:[0-9])*[0-9](?:[0-9])*$/ = nil if an alpha present there, else 0 only numeric
      # Attribution : http://stackoverflow.com/questions/1240674/regex-match-a-string-containing-numbers-and-letters-but-not-a-string-of-just-nu
      #
      # if ":" detected do: (str.gsub("%2f","/").to_sym) as key else (str.gsub("%2f","/"))
      result = nil
      if the_path == "/"
        result = self
      else
        object_stack = [(self)]
        path_stack = the_path.split("/")
        path_stack.to_enum.each do |path_element|
          element = nil
          if path_element.size > 0
            if (path_element =~ /^(?:[0-9])*[0-9](?:[0-9])*$/) == 0
              element = path_element.to_i
            else
              element = path_element
              element.gsub!("%2f","/")
              if element[0] == ":"
                element = element[(1..-1)].to_sym
              end
            end
          end
          if element
            result = object_stack.first[(element)]
            if result.is_a?(NilClass)
              break
            else
              object_stack.unshift(result)
            end
          else
            # ignore double slashes? '//'
            # break
          end
        end
      end
      result
    end

gxg_export() click to toggle source

    # File lib/gxg/gxg_augmented.rb, line 3951
    def gxg_export()
      result = {:type => "Array", :content => []}
      export_db = [{:parent => nil, :parent_selector => nil, :object => self, :record => result}]
      children_of = Proc.new do |the_parent=nil|
        list = []
        export_db.each do |node|
          if node[:parent].object_id == the_parent.object_id
            list << node
          end
        end
        list
      end
      export_record = Proc.new do |the_value|
        if the_value.is_any?(Integer, Float, String)
          {:type => (the_value.class.to_s), :content => the_value}
        else
          {:type => (the_value.class.to_s), :content => the_value.to_s}
        end
      end
      # Build up export_db:
      self.search do |the_value, the_selector, the_container|
        if the_value.is_a?(::Hash)
          export_db << {:parent => the_container, :parent_selector => the_selector.clone, :object => the_value, :record => {:type => "Hash", :content => {}}}
        else
          if the_value.is_a?(::Array)
            export_db << {:parent => the_container, :parent_selector => the_selector.clone, :object => the_value, :record => {:type => "Array", :content => []}}
          else
            export_db << {:parent => the_container, :parent_selector => the_selector.clone, :object => the_value, :record => export_record.call(the_value)}
          end
        end
      end
      # Collect children export content:
      link_db =[(export_db[0])]
      while link_db.size > 0 do
        entry = link_db.shift
        children_of.call(entry[:object]).each do |the_child|
          entry[:record][:content][(the_child[:parent_selector])] = the_child[:record]
          if the_child[:object].is_any?(Hash, Array)
            link_db << the_child
          end
        end
      end
      #
      result
    end

iterative(&block) click to toggle source

    # File lib/gxg/gxg_augmented.rb, line 3728
    def iterative(&block)
      result = []
      visit = Proc.new do |the_node=nil, accumulator=[]|
        node_stack = []
        if the_node
          node_stack << ({:parent => nil, :parent_selector => nil, :object => (the_node)})
          while (node_stack.size > 0) do
            a_node = node_stack.shift
            #
            if a_node[:object].is_any?(::Hash, ::Struct, ::GxG::Database::PersistedHash)
              a_node[:object].each_pair do |the_key, the_value|
                node_stack << ({:parent => a_node[:object], :parent_selector => the_key, :object => the_value})
              end
            end
            if a_node[:object].is_any?(::Array, ::GxG::Database::PersistedArray)
              a_node[:object].each_with_index do |the_value, the_index|
                node_stack << ({:parent => a_node[:object], :parent_selector => the_index, :object => the_value})
              end
            end
            #
            accumulator << a_node
          end
        end
        accumulator
      end
      #
      children_of = Proc.new do |the_db=[], the_parent=nil|
        list = []
        the_db.each do |node|
          if node[:parent].object_id == the_parent.object_id
            list << node
          end
        end
        list
      end
      #
      begin
        database = visit.call(self,[])
        link_db = children_of.call(database, self)
        if block.respond_to?(:call)
          while (link_db.size > 0) do
            entry = link_db.shift
            unless entry[:object].object_id == self.object_id
              # calls with parameters: the_value, the_key/the_index (the_selector), the_container
              raw_result = block.call(entry[:object], entry[:parent_selector], entry[:parent])
              if raw_result
                result << raw_result
              end
            end
            if entry[:object].object_id != nil.object_id
              children = children_of.call(database, entry[:object])
              children.each do |child|
                link_db << child
              end
            end
          end
        end
        #
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {}})
      end
      #
      result
    end

paths_to(the_object=nil,base_path="") click to toggle source

    # File lib/gxg/gxg_augmented.rb, line 3813
    def paths_to(the_object=nil,base_path="")
      # new idea here:
      search_results = []
      unless base_path[0] == "/"
        base_path = ("/" << base_path)
      end
      if base_path.size > 1
        path_stack = base_path.split("/")[1..-1].reverse
      else
        path_stack = []
      end
      origin = self.get_at_path(base_path)
      container_stack = [{:selector => nil, :container => origin}]
      find_container = Proc.new do |the_container|
        result = nil
        container_stack.each_with_index do |entry, index|
          if entry[:container] == the_container
            result = entry
            break
          end
        end
        result
      end
      last_container = origin
      found = false
      # tester = {:a=>1, :b=>2, :c=>[0, 5], :testing=>{:d=>4.0, :e=>0.9, :f => nil}}
      if origin.is_any?(::Hash, ::Array, ::Struct, ::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
        origin.process! do |the_value, selector, container|
          if last_container.object_id != container.object_id
            container_record = find_container.call(container)
            if container_record
              path_stack = container_record[:prefix].split("/").reverse
              if path_stack.size == 0
                path_stack << ""
              end
            end
            last_container = container
          end
          if selector.is_a?(Symbol)
            safe_key = (":" + selector.to_s)
          else
            safe_key = selector.to_s
          end
          safe_key.gsub!("/","%2f")
          path_stack.unshift(safe_key)
          # compare the_value
          found = false
          if (the_value == the_object)
            found = true
          end
          if found
            search_results << ("/" << path_stack.reverse.join("/"))
          end
          #
          if the_value.is_any?(::Array, ::Hash, ::Struct, ::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
            container_stack.unshift({:selector => selector, :container => the_value, :prefix => (path_stack.reverse.join("/"))})
          end
          path_stack.shift
          #
          nil
        end
      else
        search_results << ("/" << path_stack.join("/"))
      end
      search_results
    end

process(&block) click to toggle source

    # File lib/gxg/gxg_augmented.rb, line 3793
    def process(&block)
      result = self.clone
      result.iterative(&block)
      result
    end

process!(&block) click to toggle source

    # File lib/gxg/gxg_augmented.rb, line 3799
    def process!(&block)
      self.iterative(&block)
      self
    end

search(&block) click to toggle source

    # File lib/gxg/gxg_augmented.rb, line 3804
    def search(&block)
      results = []
      if block.respond_to?(:call)
        results = self.iterative(&block)
      end
      results
    end

set_at_path(the_path="/",the_value=nil) click to toggle source

    # File lib/gxg/gxg_augmented.rb, line 3920
    def set_at_path(the_path="/",the_value=nil)
      result = nil
      if the_path != "/"
        container = self.get_at_path(::File::dirname(the_path))
        if container
          raw_selector = ::File::basename(the_path)
          selector = nil
          if raw_selector.size > 0
            if (raw_selector =~ /^(?:[0-9])*[0-9](?:[0-9])*$/) == 0
              selector = raw_selector.to_i
            else
              selector = raw_selector
              selector.gsub!("%2f","/")
              if selector[0] == ":"
                selector = selector[(1..-1)].to_sym
              end
            end
          end
          if selector
            container[(selector)] = the_value
            result = container[(selector)]
          else
            # ignore double slashes? '//'
            # break
          end
          #
        end
      end
      result
    end