Class: Array
- Defined in:
- lib/openc3/core_ext/array.rb,
lib/openc3/io/json_rpc.rb,
lib/openc3/config/meta_config_parser.rb
Overview
OpenC3 specific additions to the Ruby Array class
Instance Method Summary collapse
-
#as_json(options = nil) ⇒ Object
:nodoc:.
-
#clone_to_f ⇒ Array
Cloned array after all elements called to_f.
-
#histogram(num_buckets = nil, numeric = false) ⇒ Array<Array(first_value, last_value, num_values)>
Array of buckets which are arrays containing the first value that is found in the bucket, the last value found in the bucket, and the total number of values in the bucket.
-
#index_gt_eq(value) ⇒ Fixnum
Returns the index of the last element which is greater than or equal to the passed in value.
-
#index_lt_eq(value) ⇒ Fixnum
Returns the index of the first element which is less than or equal to the passed in value.
-
#inspect(max_elements = 10) ⇒ String
String representation of the array.
-
#max_with_index ⇒ Object
Returns the maximum value and its index.
-
#mean ⇒ Object
return [Float] The mean of all the elements in the array.
-
#min_with_index ⇒ Object
Returns the minimum value and its index.
-
#nearest_index(value, ordered_data = true) ⇒ Integer
Returns the array index nearest to the passed in value.
-
#old_inspect ⇒ Object
Redefine inspect to only print for small numbers of items.
-
#range_containing(start_value, end_value) ⇒ Range
Returns the range of array elements which contain both the start value and end value.
-
#range_within(start_value, end_value) ⇒ Range
Returns the range of array elements which within both the start value and end value.
-
#squared ⇒ Object
return [Array] A new array with each value of the original squared.
-
#sum ⇒ Numeric
The sum of all the elements in the array.
- #to_meta_config_yaml(indentation = 0) ⇒ Object
Instance Method Details
#as_json(options = nil) ⇒ Object
:nodoc:
111 112 113 |
# File 'lib/openc3/io/json_rpc.rb', line 111 def as_json( = nil) #:nodoc: map { |v| v.as_json() } end |
#clone_to_f ⇒ Array
Returns Cloned array after all elements called to_f.
44 45 46 47 48 49 50 |
# File 'lib/openc3/core_ext/array.rb', line 44 def clone_to_f new_array = self.class.new(0) self.each do |value| new_array << value.to_f end new_array end |
#histogram(num_buckets = nil, numeric = false) ⇒ Array<Array(first_value, last_value, num_values)>
Returns Array of buckets which are arrays containing the first value that is found in the bucket, the last value found in the bucket, and the total number of values in the bucket.
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 |
# File 'lib/openc3/core_ext/array.rb', line 309 def histogram(num_buckets = nil, numeric = false, &) buckets = {} # Count the occurrence of each value self.each do |value| buckets[value] ||= 0 buckets[value] += 1 end # Sort buckets by value, use block for sorting if given if block_given? sorted_buckets = buckets.sort { |x, y| yield(x, y) } else sorted_buckets = buckets.sort end reduced_buckets = [] if num_buckets # Validate num_buckets raise "Invalid num_buckets #{num_buckets}" if num_buckets.to_i <= 0 # Handle histogram types if numeric # Numeric histograms use the same sized range for each bucket first_value = sorted_buckets[0][0] last_value = sorted_buckets[-1][0] delta = last_value - first_value bucket_size = delta.to_f / num_buckets.to_f integers = false integers = true if first_value.kind_of?(Integer) and last_value.kind_of?(Integer) if integers bucket_size = bucket_size.ceil last_value = first_value + (bucket_size * num_buckets) - 1 delta = last_value - first_value (delta + 1).times do |index| buckets[first_value + index] ||= 0 end if block_given? sorted_buckets = buckets.sort { |val1, val2| yield(val1, val2) } else sorted_buckets = buckets.sort end end bucket_ranges = [] current_value = first_value num_buckets.times do |bucket_index| if bucket_index == (num_buckets - 1) bucket_ranges[bucket_index] = (current_value)..(last_value) else if integers bucket_ranges[bucket_index] = (current_value)..(current_value + bucket_size - 1) else bucket_ranges[bucket_index] = (current_value)..(current_value + bucket_size) end end current_value += bucket_size end # Build the final buckets first_index = 0 sorted_index = 0 num_buckets.times do |bucket_index| break if sorted_index > (sorted_buckets.length - 1) sum = 0 bucket_range = bucket_ranges[bucket_index] while bucket_range.include?(sorted_buckets[sorted_index][0]) sum += sorted_buckets[sorted_index][1] sorted_index += 1 break if sorted_index > (sorted_buckets.length - 1) end reduced_buckets[bucket_index] = [bucket_range.first, bucket_range.last, sum] end else # Non-numeric histograms use the same number of items per bucket items_per_bucket = sorted_buckets.length / num_buckets.to_i items_per_bucket = 1 if items_per_bucket < 1 bucket_sizes = [items_per_bucket] * num_buckets excess_items = sorted_buckets.length - (items_per_bucket * num_buckets) if excess_items > 0 bucket_sizes.length.times do |bucket_size_index| break if excess_items <= 0 bucket_sizes[bucket_size_index] += 1 excess_items -= 1 end end # Build the final buckets first_index = 0 num_buckets.times do |bucket_index| break if first_index > (sorted_buckets.length - 1) if bucket_index == (num_buckets - 1) last_index = sorted_buckets.length - 1 else last_index = first_index + bucket_sizes[bucket_index] - 1 last_index = sorted_buckets.length - 1 if last_index > (sorted_buckets.length - 1) end sum = 0 sorted_buckets[first_index..last_index].each { |_key, value| sum += value } reduced_buckets[bucket_index] = [sorted_buckets[first_index][0], sorted_buckets[last_index][0], sum] first_index = first_index + bucket_sizes[bucket_index] end end else sorted_buckets.each { |key, value| reduced_buckets << [key, key, value] } end reduced_buckets end |
#index_gt_eq(value) ⇒ Fixnum
Returns the index of the last element which is greater than or equal to the passed in value.
NOTE: This routine only works on sorted data!
183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/openc3/core_ext/array.rb', line 183 def index_gt_eq(value) index = nearest_index(value) last_index = self.length - 1 # Keep moving forward if self[index - 1] == value to move past duplicates while index < last_index and self[index + 1] == value index += 1 end return index if self[index] >= value index += 1 if (self.length - 1) > index return index end |
#index_lt_eq(value) ⇒ Fixnum
Returns the index of the first element which is less than or equal to the passed in value.
NOTE: This routine only works on sorted data!
161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/openc3/core_ext/array.rb', line 161 def index_lt_eq(value) index = nearest_index(value) # Keep backing up if self[index - 1] == value to move past duplicates while index > 0 and self[index - 1] == value index -= 1 end return index if self[index] <= value index -= 1 if index > 0 return index end |
#inspect(max_elements = 10) ⇒ String
Returns String representation of the array.
35 36 37 38 39 40 41 |
# File 'lib/openc3/core_ext/array.rb', line 35 def inspect(max_elements = 10) if self.length <= max_elements old_inspect() else '#<' + self.class.to_s + ':' + self.object_id.to_s + '>' end end |
#max_with_index ⇒ Object
Returns the maximum value and its index
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/openc3/core_ext/array.rb', line 254 def max_with_index maximum = nil maximum_index = nil if self.length > 0 maximum = self[0] maximum_index = 0 (1..(self.length - 1)).each do |index| value = self[index] if value > maximum maximum = value maximum_index = index end end end return [maximum, maximum_index] end |
#mean ⇒ Object
return [Float] The mean of all the elements in the array
241 242 243 244 245 |
# File 'lib/openc3/core_ext/array.rb', line 241 def mean return 0.0 if self.empty? return self.sum / self.length.to_f end |
#min_with_index ⇒ Object
Returns the minimum value and its index
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 |
# File 'lib/openc3/core_ext/array.rb', line 276 def min_with_index minimum = nil minimum_index = nil if self.length > 0 minimum = self[0] minimum_index = 0 (1..(self.length - 1)).each do |index| value = self[index] if value < minimum minimum = value minimum_index = index end end end return [minimum, minimum_index] end |
#nearest_index(value, ordered_data = true) ⇒ Integer
Returns the array index nearest to the passed in value. This only makes sense for numerical arrays containing integers or floats. It has an optimized algorithm if the array is sorted but will fail if passed unsorted data with the sorted option.
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/openc3/core_ext/array.rb', line 60 def nearest_index(value, ordered_data = true) raise "Cannot search on empty array" if self.empty? if ordered_data last_index = self.length - 1 first_value = self[0].to_f last_value = self[-1].to_f return 0 if first_value == last_value slope = last_index.to_f / (last_value - first_value) offset = -(slope * first_value) guess_index = ((slope * value.to_f) + offset).to_i # Return immediately for boundary conditions return 0 if guess_index < 0 return last_index if guess_index > last_index # Verify guess index previous_guess_index = nil previous_guess_value = nil # While in the valid range of indexes while guess_index >= 0 and guess_index <= last_index # Retrieve the value at our current guess index guess_value = self[guess_index] # We're done if we found the exact value return guess_index if guess_value == value if previous_guess_value # Determine if we did better or worse # Was previous guess better or worse? if (guess_value - value).abs <= (previous_guess_value - value).abs # Previous Guess Worse or the same if guess_value > value # Moving with decreasing indexes if previous_guess_value > value # Still moving in right direction previous_guess_index = guess_index guess_index -= 1 else # We passed the value return guess_index end else # guess_value < value and moving with increasing indexes if previous_guess_value < value # Still moving in right direction previous_guess_index = guess_index guess_index += 1 else # We passed the value return guess_index end end else # Previous Guess Better return previous_guess_index end else # Move to the next point previous_guess_index = guess_index if guess_value > value guess_index -= 1 else # guess_value < value guess_index += 1 end end previous_guess_value = guess_value end # Return our best guess return 0 if guess_index < 0 return last_index else # Brute force search # Calculate the initial delta min_delta = (self[0] - value).abs closest_index = 0 self.each_with_index do |self_value, index| # Calculate the delta between the current value and value we are # searching for delta = (value - self_value).abs # If the newly calculate delta is less than or equal to are previous # minimum delta then we proceed if delta <= min_delta # There is a special case if the delta is equal to the previously # calculated delta. We want to round up in this case so we check if # the value we are searching for is greater than the current value. # If so we skip this value since we don't want to round down. next if (delta == min_delta) and (value > self_value) min_delta = delta closest_index = index end end return closest_index end end |
#old_inspect ⇒ Object
Redefine inspect to only print for small numbers of items. Prevents exceptions taking forever to be raise with large objects. See blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/105145
30 |
# File 'lib/openc3/core_ext/array.rb', line 30 alias old_inspect inspect |
#range_containing(start_value, end_value) ⇒ Range
Returns the range of array elements which contain both the start value and end value.
NOTE: This routine only works on sorted data!
208 209 210 211 212 |
# File 'lib/openc3/core_ext/array.rb', line 208 def range_containing(start_value, end_value) raise "end_value: #{end_value} must be greater than start_value: #{start_value}" if end_value < start_value Range.new(index_lt_eq(start_value), index_gt_eq(end_value)) end |
#range_within(start_value, end_value) ⇒ Range
Returns the range of array elements which within both the start value and end value.
NOTE: This routine only works on sorted data!
224 225 226 227 228 229 230 231 |
# File 'lib/openc3/core_ext/array.rb', line 224 def range_within(start_value, end_value) raise "end_value: #{end_value} must be greater than start_value: #{start_value}" if end_value < start_value range = Range.new(index_gt_eq(start_value), index_lt_eq(end_value)) # Sometimes we get a backwards range so check for that and reverse it range = Range.new(range.last, range.first) if range.last < range.first range end |
#squared ⇒ Object
return [Array] A new array with each value of the original squared
248 249 250 |
# File 'lib/openc3/core_ext/array.rb', line 248 def squared self.map { |value| value * value } end |
#sum ⇒ Numeric
Returns The sum of all the elements in the array.
235 236 237 |
# File 'lib/openc3/core_ext/array.rb', line 235 def sum self.inject(0, :+) end |
#to_meta_config_yaml(indentation = 0) ⇒ Object
29 30 31 |
# File 'lib/openc3/config/meta_config_parser.rb', line 29 def (indentation = 0) Psych.dump(self).split("\n")[1..-1].join("\n#{' ' * indentation}") end |