#------------------------------------------------------------------------- # # Open Source License/Disclaimer, Forecast Systems Laboratory NOAA/OAR/FSL, # 325 Broadway Boulder, CO 80305 # # This software is distributed under the Open Source Definition, which may # be found at http://www.opensource.org/osd.html. # # In particular, redistribution and use in source and binary forms, with or # without modification, are permitted provided that the following conditions # are met: # # . Redistributions of source code must retain this notice, this list # of conditions and the following disclaimer. # # . Redistributions in binary form must provide access to this notice, # this list of conditions and the following disclaimer, and the # underlying source code. # # . All modifications to this software must be clearly documented, and # are solely the responsibility of the agent making the modifications. # # . If significant modifications or enhancements are made to this # software, the FSL Software Policy Manager (softwaremgr@fsl.noaa.gov) # should be notified. # #------------------------------------------------------------------------- # # THIS SOFTWARE AND ITS DOCUMENTATION ARE IN THE PUBLIC DOMAIN AND ARE # FURNISHED "AS IS." THE AUTHORS, THE UNITED STATES GOVERNMENT, ITS # INSTRUMENTALITIES, OFFICERS, EMPLOYEES, AND AGENTS MAKE NO WARRANTY, # EXPRESS OR IMPLIED, AS TO THE USEFULNESS OF THE SOFTWARE AND DOCUMENTATION # FOR ANY PURPOSE. THEY ASSUME NO RESPONSIBILITY (1) FOR THE USE OF THE # SOFTWARE AND DOCUMENTATION; OR (2) TO PROVIDE TECHNICAL SUPPORT TO USERS. # #------------------------------------------------------------------------- # # # WARNING: This is OPAQUE Facility Division (FD) Software. All OPAQUE FD # Software is subject to change without notice. # The ArrayFields module implements methods which allow an Array's fields to # be indexed by name (String). This is incredibly usefull for naming the # fields of tuples (Arrays) returned from database queries module ArrayFields # given one, more field names, returns those elements def [] (*idx) idx.flatten! return self.indices(*idx) if idx.size > 1 idx = idx[0] if @fields and idx.type == String pos = @fieldpos[idx] return nil unless pos self[pos] else super end end # given one field name, assign value to this field def []= idx, value if @fields and idx.type == String pos = @fieldpos[idx] if not pos pos = size @fieldpos[idx] = pos end self[pos] = value else super end end # given one, more field names, returns those elements def indices(*idxs) idxs.flatten! if @fields idxs.collect! do |idx| idx.type == String ? @fieldpos[idx] : idx end end super(*idxs) end end # The array class is extened here with a methods which dynamically include # ArrayFields, allowing access to fields by name, when the methods fields= is # called class Array # when this method is called, extends this Array object such that it's # fields will be accessible as those in fields. a copy of fields is NOT # taken for efficiency so make your own copy of you plan to modify it! # # a = ['ford', 42] # a.fields = ['name', 'number'] # p a['name'] # >> 'ford' def fields= fields @recursive_fields = true unless defined? @recursive_fields each{|e| e.fields = fields if recursive_fields && Array === e} extend ArrayFields unless @fields @fields = fields # not a copy! @fieldpos = Hash.new @fields.each_with_index {|f,i| @fieldpos[f] = i} end attr_reader :fields attr_reader :fieldpos attr :recursive_fields, true end if $0 == __FILE__ fields = ['zero','one','two'] a = [0,1,2] a.fields = fields fields.each{|f| puts "a[#{f}]\t\t:\t\t#{a[f]}"} puts a[fields] puts a[fields.reverse] b = a.clone fields.each{|f| puts "b[#{f}]\t\t:\t\t#{b[f]}"} table = [ ['ryan',6.3], ['ahoward',5.11], ] table.fields = ['name','height'] puts table[0]['name'] puts table[0]['height'] puts table[1]['name'] puts table[1]['height'] #puts table[0]['name','height'] puts table[0][['name','height']] puts table[0]['name','height'] puts table[0].indices 'name','height' puts table[0].indices ['name','height'] end