Class: One::Pivoter
Overview
Class that can be used for mining data from lists of objects.
Instance Method Summary collapse
-
#multi_pivot(list, *pivots) ⇒ Hash
Runs multiple pivots against a list of Objects.
-
#pivot(list, options = {}) {|item| ... } ⇒ Hash
Pivots a list of Objects grouping them into an organized Hash.
Instance Method Details
#multi_pivot(list, *pivots) ⇒ Hash
Runs multiple pivots against a list of Objects.
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 158 159 160 161 162 163 164 165 |
# File 'lib/one/pivoter.rb', line 130 def multi_pivot(list, *pivots) = pivots.pop if pivots.last.is_a?(Hash) ||= {} delimiter = [:delimiter] || "[PIVOT]" pivoted = nil pass = 0 while pivots.length > 0 p = pivots.shift # handle the case where the pivots are One::Pivot objects = {} if p.is_a?(One::Pivot) [:identifier] = p.identifier p = p.pivot_proc end if pass == 0 pivoted = pivot(list, , &p) else new_pivoted = {} pivoted.each do |old_key, old_list| tmp_pivoted = pivot(old_list, , &p) tmp_pivoted.each do |key, list| new_key = "#{safe_key(old_key)}#{delimiter}#{safe_key(key)}" new_pivoted[new_key] = list end end pivoted = new_pivoted end pass += 1 end pivoted end |
#pivot(list, options = {}) {|item| ... } ⇒ Hash
Pivots a list of Objects grouping them into an organized Hash.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 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 |
# File 'lib/one/pivoter.rb', line 33 def pivot(list, ={}, &block) pivoted = {} semaphore = Mutex.new lists = list.each_slice(chunk_size(list)).to_a loops = 0 reactor_running = EM.reactor_running? work = Proc.new do lists.each do |sub_list| pivot_operation = Proc.new do sub_list.each do |item| # potential long running operation with blocking IO value = yield(item) # notify observers that a pivot block was just called identifier = [:identifier] || "#{item.hash}:#{block.hash}" changed # potential long running operation with blocking IO notify_observers(identifier, item, value) semaphore.synchronize { if value.is_a?(Array) if value.empty? pivoted[nil] ||= [] pivoted[nil] << item else value.each do |val| pivoted[val] ||= [] pivoted[val] << item end end else pivoted[value] ||= [] pivoted[value] << item end } end end pivot_callback = Proc.new do semaphore.synchronize { loops += 1 EM.stop if loops == lists.length && !reactor_running } end EM.defer(pivot_operation, pivot_callback) end end if reactor_running work.call else EM.run &work end pivoted end |