Class: Alf::Types::Ordering
- Inherits:
-
Object
- Object
- Alf::Types::Ordering
- Defined in:
- lib/alf/types/ordering.rb
Overview
Defines an ordering on tuple attributes
Constant Summary collapse
- ArrayOfArray =
->(x){ x.is_a?(Array) && x.all?{|y| y.is_a?(Array)} }
- ArrayWithDirections =
->(x){ x.each_with_index.all?{|elm,i| (i%2==0) || elm.to_s =~ /^asc|desc$/ } }
- EMPTY =
Ordering.new([])
Instance Attribute Summary collapse
-
#sorter ⇒ Proc
readonly
A Proc object that sorts tuples according to this ordering.
Class Method Summary collapse
Instance Method Summary collapse
-
#<=(other) ⇒ Object
Check if this ordering subsumes another one.
-
#[](attribute) ⇒ Symbol
Returns the directions associated with an attribute name, nil if no such attribute.
-
#compare(t1, t2) ⇒ -1, 0 or 1
Compares two tuples according to this ordering.
-
#dive(attr) ⇒ Ordering
Dives into a relation/tuple valued attribute
attr. -
#initialize(ordering = []) ⇒ Ordering
constructor
Creates an ordering instance.
-
#merge(other, &bl) ⇒ Ordering
(also: #+)
Computes the union of this ordering with another one.
-
#reverse ⇒ Ordering
Reverse this ordering.
-
#selectors ⇒ Array[Selector]
Returns the list of selectors.
-
#to_attr_list ⇒ AttrList
Converts to an attribute list.
-
#to_lispy ⇒ String
Returns a lispy expression.
-
#to_ruby_literal ⇒ String
(also: #to_s, #inspect)
Returns a ruby literal for this ordering.
-
#total(keys, &bl) ⇒ Ordering
Returns a total ordering given some key definitions.
Constructor Details
#initialize(ordering = []) ⇒ Ordering
Creates an ordering instance
40 41 42 43 |
# File 'lib/alf/types/ordering.rb', line 40 def initialize(ordering = []) super @sorter = lambda{|t1,t2| compare(t1, t2) } end |
Instance Attribute Details
#sorter ⇒ Proc (readonly)
Returns a Proc object that sorts tuples according to this ordering.
35 36 37 |
# File 'lib/alf/types/ordering.rb', line 35 def sorter @sorter end |
Class Method Details
.new(array) ⇒ Object
9 10 11 |
# File 'lib/alf/types/ordering.rb', line 9 def self.new(array) super(array.map{|(x,y)| [Selector.coerce(x), y.to_sym] }) end |
Instance Method Details
#<=(other) ⇒ Object
Check if this ordering subsumes another one.
154 155 156 157 |
# File 'lib/alf/types/ordering.rb', line 154 def <=(other) size = reused_instance.size reused_instance == other.to_a[0...size] end |
#[](attribute) ⇒ Symbol
Returns the directions associated with an attribute name, nil if no such attribute.
52 53 54 55 56 |
# File 'lib/alf/types/ordering.rb', line 52 def [](attribute) attribute = Selector.coerce(attribute) pair = reused_instance.find{|p| p.first == attribute } pair && pair.last end |
#compare(t1, t2) ⇒ -1, 0 or 1
Compares two tuples according to this ordering.
Both t1 and t2 should have all attributes used by this ordering. Strange results may appear if it’s not the case.
67 68 69 70 71 72 73 74 75 76 |
# File 'lib/alf/types/ordering.rb', line 67 def compare(t1, t2) extract = proc{|t,x| Array(x).inject(t){|m,a| m[a]} } reused_instance.each do |atr, dir| x, y = extract[t1,atr], extract[t2,atr] comp = Support.robust_compare(x, y) comp *= -1 if dir == :desc return comp unless comp == 0 end return 0 end |
#dive(attr) ⇒ Ordering
Dives into a relation/tuple valued attribute attr.
139 140 141 142 143 144 |
# File 'lib/alf/types/ordering.rb', line 139 def dive(attr) attrs = reused_instance .map {|(s,d)| [s.dive(attr), d] } .reject{|(s,d)| s.nil? } Ordering.new(attrs) end |
#merge(other, &bl) ⇒ Ordering Also known as: +
Computes the union of this ordering with another one.
The union is simply defined by extension of self with other’s attributes and directions. Duplicates are automatically removed.
When a conflict arises (same attribute but not same direction), the block is yield with the attribute name, then self‘s and other’s directions as arguments. The block is expected to return the direction to use to the attribute. A default block is provided that always favors the direction found in other.
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/alf/types/ordering.rb', line 91 def merge(other, &bl) bl ||= lambda{|attr,d1,d2| d2 } other = Ordering.coerce(other) attributes = self.selectors | other.selectors directions = attributes.to_a.map{|a| left, right = self[a], other[a] direction = if left.nil? or right.nil? left || right elsif left == right left else bl.call(a, left, right) end [a, direction] } Ordering.new(directions) end |
#reverse ⇒ Ordering
Reverse this ordering.
114 115 116 117 118 |
# File 'lib/alf/types/ordering.rb', line 114 def reverse Ordering.new(reused_instance.map{|attr,dir| [ attr, dir == :asc ? :desc : :asc ] }) end |
#selectors ⇒ Array[Selector]
Returns the list of selectors
149 150 151 |
# File 'lib/alf/types/ordering.rb', line 149 def selectors reused_instance.map(&:first) end |
#to_attr_list ⇒ AttrList
Converts to an attribute list.
163 164 165 |
# File 'lib/alf/types/ordering.rb', line 163 def to_attr_list AttrList.new(selectors.map{|x| Array(x).first }) end |
#to_lispy ⇒ String
Returns a lispy expression.
170 171 172 |
# File 'lib/alf/types/ordering.rb', line 170 def to_lispy Support.to_ruby_literal(to_a.map{|(x,d)| [x.outcoerce, d]}) end |
#to_ruby_literal ⇒ String Also known as: to_s, inspect
Returns a ruby literal for this ordering.
177 178 179 |
# File 'lib/alf/types/ordering.rb', line 177 def to_ruby_literal "Alf::Ordering[#{Support.to_ruby_literal(reused_instance)}]" end |
#total(keys, &bl) ⇒ Ordering
Returns a total ordering given some key definitions.
123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/alf/types/ordering.rb', line 123 def total(keys, &bl) list = to_attr_list if k = keys.to_a.find{|k| k.to_attr_list.subset_of?(list) } self elsif k = keys.first merge(k.to_ordering){|k,d1,d2| d1 } elsif bl && (key = bl.call.to_attr_list) merge(key.to_ordering){|k,d1,d2| d1 } else raise NotSupportedError, "Unable to find a total order (no key available)" end end |