Class: Rarff::Relation

Inherits:
Object
  • Object
show all
Defined in:
lib/rarff.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name = '') ⇒ Relation

Returns a new instance of Relation.



121
122
123
124
125
126
# File 'lib/rarff.rb', line 121

def initialize(name='')
  @name = name
  @attributes = Array.new
  @instances = Array.new
  @comments = Array.new
end

Instance Attribute Details

#attributesObject

Returns the value of attribute attributes.



118
119
120
# File 'lib/rarff.rb', line 118

def attributes
  @attributes
end

#commentsObject

Returns the value of attribute comments.



118
119
120
# File 'lib/rarff.rb', line 118

def comments
  @comments
end

#instancesObject

Returns the value of attribute instances.



118
119
120
# File 'lib/rarff.rb', line 118

def instances
  @instances
end

#nameObject

Returns the value of attribute name.



118
119
120
# File 'lib/rarff.rb', line 118

def name
  @name
end

Instance Method Details

#assign_or_build_attr(j, attr_type) ⇒ Object



187
188
189
190
191
192
193
# File 'lib/rarff.rb', line 187

def assign_or_build_attr(j, attr_type)
  if @attributes[j].is_a?(Attribute)
    @attributes[j].type = attr_type
  else
    @attributes[j] = Attribute.new("Attr#{j}", attr_type)
  end
end

#create_attributesObject



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/rarff.rb', line 166

def create_attributes
  attr_pass = true

  @instances.each_index { |i|
    @instances[i].each_index { |j|
      if @instances[i][j].class != String
        assign_or_build_attr(j, ATTRIBUTE_NUMERIC) if attr_pass
      elsif @instances[i][j] =~ /^\-?\d+\.?\d*$/
        # TODO: Should I have a separate to_i conversion, or is to_f sufficient?
        @instances[i][j] = @instances[i][j].to_f
        assign_or_build_attr(j, ATTRIBUTE_NUMERIC) if attr_pass
      else
        assign_or_build_attr(j, ATTRIBUTE_STRING) if attr_pass
      end
    }

    attr_pass = false
  }
end

#expand_sparse(str) ⇒ Object



195
196
197
198
199
200
201
202
# File 'lib/rarff.rb', line 195

def expand_sparse(str)
  arr = Array.new(@attributes.size, 0)
  str.gsub(/^\s*\{(.*)\}\s*$/, "\\1").split(/\s*\,\s*/).map { |pr|
    pra = pr.split(/\s/)
    arr[pra[0].to_i] = pra[1]
  }
  arr
end

#parse(str) ⇒ Object



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/rarff.rb', line 129

def parse(str)
  in_data_section = false

  # TODO: Doesn't handle commas in quoted attributes.
  str.split("\n").each_with_index { |line, idx|
    next if line =~ /^\s*$/
    next if line.my_scan(/^\s*#{COMMENT_MARKER}/) { @comments << Comment.new(line.slice(1..-1), idx+1)}
    next if line.my_scan(/^\s*#{RELATION_MARKER}\s*(.*)\s*$/i) { |name| @name = name }
    next if line.my_scan(/^\s*#{ATTRIBUTE_MARKER}\s*([^\s]*)\s+(.*)\s*$/i) { |name, type|
      @attributes.push(Attribute.new(name, type))
    }
    next if line.my_scan(/^\s*#{DATA_MARKER}/i) { in_data_section = true }
    next if in_data_section == false ## Below is data section handling
                                     #      next if line.gsub(/^\s*(.*)\s*$/, "\\1").my_scan(/^\s*#{SPARSE_ARFF_BEGIN}(.*)#{SPARSE_ARFF_END}\s*$/) { |data|
    next if line.gsub(/^\s*(.*)\s*$/, "\\1").my_scan(/^#{ESC_SPARSE_ARFF_BEGIN}(.*)#{ESC_SPARSE_ARFF_END}$/) { |data|
      # Sparse ARFF
      # TODO: Factor duplication with non-sparse data below
      @instances << expand_sparse(data.first)
      create_attributes()
    }
    next if line.my_scan(/^\s*(.*)\s*$/) { |data|
      @instances << data.first.split(/,\s*/).map { |field|
        # Remove outer single quotes on strings, if any ('foo bar' --> foo bar)
        field.gsub(/^\s*\'(.*)\'\s*$/, "\\1")
      }
      create_attributes()
    }
  }
end

#to_arffObject



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/rarff.rb', line 205

def to_arff
  RELATION_MARKER + " #{@name}\n" +
      @attributes.map { |attr| attr.to_arff }.join("\n") +
      "\n" +
      DATA_MARKER + "\n" +
      @instances.map { |inst|
        inst.map_with_index { |col, i|
          # Quote strings with spaces.
          # TODO: Doesn't handle cases in which strings already contain
          # quotes or are already quoted.
          if @attributes[i].type =~ /^#{ATTRIBUTE_STRING}$/i
            if col =~ /\s+/
              col = "'" + col + "'"
            end
          elsif @attributes[i].type =~ /^#{ATTRIBUTE_DATE}/i ## Hack comparison. Ugh.
            col = '"' + col + '"'
          end
          col
        }.join(', ')
      }.join("\n")
end

#to_sObject



228
229
230
# File 'lib/rarff.rb', line 228

def to_s
  to_arff
end