Class: Array

Inherits:
Object show all
Defined in:
lib/qualitysmith_extensions/array/average.rb,
lib/qualitysmith_extensions/array/classify.rb,
lib/qualitysmith_extensions/array/group_by.rb,
lib/qualitysmith_extensions/array/sequence.rb,
lib/qualitysmith_extensions/array/shell_escape.rb,
lib/qualitysmith_extensions/array/expand_ranges.rb,
lib/qualitysmith_extensions/array/to_a_recursive.rb,
lib/qualitysmith_extensions/array/to_query_string.rb

Overview

Author

Tyler Rick

Copyright

Copyright © 2007 QualitySmith, Inc.

License

Ruby License

Submit to Facets?

Yes.

++

Instance Method Summary collapse

Instance Method Details

#after(value) ⇒ Object

Returns the value after the given value. The value before the last is the first. Returns nil if the given value is not in the array.

Example:
     sequence = ['a', 'b', 'c']
     sequence.after('a')           => 'b'
     sequence.after('b')           => 'c'
     sequence.after('c')           => 'a'
     sequence.after('d')           => nil


34
35
36
37
# File 'lib/qualitysmith_extensions/array/sequence.rb', line 34

def after(value)
  return nil unless include? value
  self[(index(value).to_i + 1) % length]
end

#averageObject

Calculates the arithmetic average (mean) of the elements in the array as a Float.

irb -> [1, 3, 3].average
    => 2.33333333333333


14
15
16
17
18
19
20
21
# File 'lib/qualitysmith_extensions/array/average.rb', line 14

def average
  if self.size == 0
    raise ZeroDivisionError
  end
  self.inject(0.0) do |sum, item|
    sum + item.to_f
  end / self.size
end

#before(value) ⇒ Object

Returns the value previous to the given value. The value previous to the first is the last. Returns nil if the given value is not in the array.

Example:
     sequence = ['a', 'b', 'c']
     sequence.before('a')           => 'c'
     sequence.before('b')           => 'a'
     sequence.before('c')           => 'b'
     sequence.before('d')           => nil


19
20
21
22
# File 'lib/qualitysmith_extensions/array/sequence.rb', line 19

def before(value)
  return nil unless include? value
  self[(index(value).to_i - 1) % length]
end

#classify(&block) ⇒ Object

Classifies the array by the return value of the given block and returns a hash of => array of elements pairs.

The block is called once for each element of the array, passing the element as parameter.

Breaks an array into a hash of smaller arrays, making a new group for each unique value returned by the block. Each unique value becomes a key in the hash.

Example:
   [
     ['a', 1],
     ['a', 2],
     ['b', 3],
     ['b', 4],
   ].classify {|o| o[0]}
 =>  
   {
     "a" => [['a', 1], ['a', 2]], 
     "b" => [['b', 3], ['b', 4]]
   }


37
38
39
40
41
42
43
44
# File 'lib/qualitysmith_extensions/array/classify.rb', line 37

def classify(&block)
  hash = {}
  each do |element|
    classification = yield(element)
    (hash[classification] ||= []) << element
  end
  hash
end

#expand_rangesObject

Expands (calls to_a on) all Ranges contained in this array, replacing the range with the list of elements that the range represents.

This is especially useful when you want to have “discontiguous ranges” like [1..3, 5..7]…

[1..3, 5..7].expand_ranges
=> [1, 2, 3, 5, 6, 7]


19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/qualitysmith_extensions/array/expand_ranges.rb', line 19

def expand_ranges
  new_array = []
  each do |item|
    silence_warnings do             # Object.to_a: warning: default `to_a' will be obsolete
      if item.respond_to?(:to_a)
        new_array.concat item.to_a
      else
        new_array.concat [item]
      end
    end
  end
  new_array
end

#group_by(column_index, *args) ⇒ Object

Breaks an array into a hash of smaller arrays, making a new group for each unique value in the specified column.

Each unique value becomes a key in the hash.

Example:
     [
        ['a', 1],
        ['a', 2],
        ['b', 3],
        ['b', 4],
     ].group_by(0)
 =>  
     "a"=>[[1], [2]], 
     "b"=>[[3], [4]]

Options:
* <tt>delete_key</tt>: deletes the key from the corresponding array if true (default true)

Example:
     [
        ['a', 1],
        ['a', 2],
        ['b', 3],
        ['b', 4],
     ].group_by(0, :delete_key => false)
 =>  
     "a"=>[['a', 1], ['a', 2]], 
     "b"=>[['b', 3], ['b', 4]]

*Notes*:
* <tt>self</tt> must be in the shape of a "table" (that is, a rectangular-shaped, two-dimensional array = an array of arrays,
  each member array being of the same size (the "width" of the table)).
* This is different from the GROUP BY in SQL in that it doesn't apply an aggregate (like sum or average) to each group -- it just returns each group unmodified.


53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/qualitysmith_extensions/array/group_by.rb', line 53

def group_by(column_index, *args)
  options = (if args.last.is_a?(Hash) then args.pop else {} end)
  hash = {}
  self.each do |row|
    row_to_keep = row.dup
    row_to_keep.delete_values_at(column_index) unless options[:delete_key] == false

    hash[row[column_index]] ||= []
    hash[row[column_index]] << row_to_keep
  end
  hash
end

#shell_escapeObject



14
15
16
# File 'lib/qualitysmith_extensions/array/shell_escape.rb', line 14

def shell_escape
  self.map(&:shell_escape)
end

#to_a_recursiveObject

A lot like array.flatten, except that it will also “flatten” ranges (by converting range to range.to_a) and any other objects that respond to to_a contained in the array in addition to arrays contained in the array. Compare with Array#expand_ranges



12
13
14
15
16
17
18
19
20
21
# File 'lib/qualitysmith_extensions/array/to_a_recursive.rb', line 12

def to_a_recursive
  map do |item|
    # Assume that all arrays contain only elements that do not respond to to_a_recursive or arrays.
    if item.respond_to? :to_a_recursive
      item.to_a_recursive
    else
      item.to_a
    end
  end
end

#to_query_string(key) ⇒ Object

Converts into a string that can be used as the query string of a URL (for example, ?key[]=val1&key[]=val2).

Example:
  [
    'Fred',
    'Sam'
  ].to_query_string('names')
  ==> "names[]=Fred&names[]=Sam"

<tt>key</tt> is the name of the key in params that will receive the array when you load the page. So, for example, if you go to page with this query string (key = "names"): <tt>?names[]=Fred&names[]=Sam</tt>, params will be have a key "names", like so: <tt>{"names"=>["Fred", "Sam"]}</tt>.


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/qualitysmith_extensions/array/to_query_string.rb', line 23

def to_query_string(key)
  elements = []
  
  self.each do |value|
    _key = key + '[]'
    if value.is_a? Array
      raise "Array#to_query_string only works on flat (1-dimensional) arrays."
    elsif value.respond_to? :to_query_string
    	value = value.to_query_string(_key)
    else
      value = CGI.escape value.to_s
    end
    elements << _key + '=' + value
  end
  
  elements.join('&')
end