Reversing 2-array axis in Ruby

Recently, I was working on a project that imports some CSV data into a dynamic database table. It needs to sort an array of floats. Along the way coding, I found myself doing something curious:

    rows = @table_class.all
    rows.each do | row |
      key = row.primary_key.to_sym
      @matches[key] = []
      row.instance_variables.each do | column |
        unless ['@id', '@repository','@primary_key','@original_values', '@new_record','@collection', '@updated_at'].include? column
          x = row.instance_variable_get(column)
          y = column.gsub(/@/, '') 
          @matches[key] << {:x => x, :y => y}
        end
      end 
      @matches[key] = @matches[key].sort_by { |match| match[:y] }
    end
    @matches

Sorting in Ruby! This smells bad. I put the data in a database for this?

The solution
The solution was to reverse the axis of the imported data, thereby enabling MySQL to sort the data for us. Instead of doing:

    n=0
    @parsed_file.each do | row |
      hash = row2hash(row)
      unless @table_class.first(:primary_key => hash[:primary_key])
        instance = @table_class.new(hash)
        if instance.save
          n+=1
          GC.start if n%50 == 0
        end
      end
    end

We can parse the file with inversed axis by doing:

    values = {}
    @parsed_file[0].enum_with_index.map do |primary_key, idx|
      if primary_key
        pk = primary_key.to_sym
        @parsed_file.collect do |row|
          if row[0]
            values[pk] = {} unless values[pk].is_a?(Hash)
            values[pk][row[0].to_sym] = row[idx]
          end
        end
      end 
    end
    n = 0 
    values.keys.each do |key|
      if values[key]
        unless @table_class.first(:primary_key => key.to_s)
          instance = @table_class.new(values[key])
          instance.primary_key = key
          if instance.save
            n+=1
            GC.start if n%50 == 0
          end
        end
      end
    end

I admit this is totally crazy code, and I don’t expect you to follow along. The rest of the class needed a bit of modifying too, but the first code example above has been simplified to:

    @matches[primary_key.to_sym] = @table_class.all(:order => [primary_key.to_sym.desc])

Ofcourse this hasn’t hurt performance, either


Trackbacks

Use the following link to trackback from your own site:
http://blog.aczid.nl/trackbacks?article_id=20


Me elsewhere: