lib/hash_op/math.rb in hash_op-0.1.0 vs lib/hash_op/math.rb in hash_op-0.2.0
- old
+ new
@@ -1,71 +1,54 @@
-require 'hash_op/deep_access'
+require 'hash_op/deep'
# A set of functions to perform mathematical operations
# on Hashes.
module HashOp
module Math
- # @param hashes [Array] of Hash instances
- # @return [Hash] summing values of the same key
- def sum(*hashes)
- hashes.flatten!
- case hashes.length
- when 0 then {}
- when 1 then hashes.first
- when 2 then sum_two(*hashes)
- else
- sum(*[sum_two(*hashes[0..1])] + hashes[2..-1])
- end
- end
- module_function :sum
-
- def sum_two(hash_a, hash_b)
- hash_b.each do |key, hash_b_value|
- if hash_a[key]
- hash_a[key] += hash_b_value
- else
- hash_a[key] = hash_b_value
- end
- end
- hash_a
- end
- module_function :sum_two
-
# Sum values in an array of hashes by grouping on a given
# key.
#
# Example:
# hashes = [
- # { group: :a, value: 1 },
- # { group: :a, value: 1 },
- # { group: :b, value: 1 }
+ # { group_1: :a, group_2: :a, value_1: 1, value_2: 1 },
+ # { group_1: :a, group_2: :b, value_1: 1, value_2: 2 },
+ # { group_1: :a, group_2: :b, value_1: 1, value_2: 2 },
+ # { group_1: :b, group_2: :c, value_1: 1, value_2: 3 }
# ]
- # HashOp::Math.sum_on_groups(hashes, :group, :value)
- # # => [
- # # { group: :a, value: 2 },
- # # { group: :b, value: 1 }
- # # ]
+ # HashOp::Math.sum_on_groups(hashes,
+ # [:group_1], [:value_1, :value_2]
+ # )
+ # => [
+ # { group_1: :a, value_1: 3, value_2: 5 },
+ # { group_1: :b, value_1: 1, value_2: 3 }
+ # ]
+ # HashOp::Math.sum_on_groups(hashes,
+ # [:group_1, :group_2], [:value_1, :value_2]
+ # )
+ # => [
+ # { group_1: :a, group_2: :a, value_1: 1, value_2: 1 },
+ # { group_1: :a, group_2: :b, value_1: 2, value_2: 4 },
+ # { group_1: :b, group_2: :c, value_1: 1, value_2: 3 }
+ # ]
#
# @param hashes [Array] the hashes to be summed
# @param group_key [Object] the key to use to group items on
# @param value_key [Object] the key of the values to sum
# @return [Array]
- def sum_on_groups(hashes, group_key, value_key)
- work_hash = hashes.inject({}) do |work, hash|
- if work[hash[group_key]].nil?
- work[hash[group_key]] = {
- group_key => hash[group_key],
- value_key => hash[value_key]
- }
- else
- work[hash[group_key]][value_key] += hash[value_key]
+ def sum_on_groups(hashes, grouping_paths, value_paths)
+ grouped_hashes = Grouping.group_on_paths(hashes, grouping_paths)
+ group_paths = Deep.paths(grouped_hashes)
+ result = group_paths.map do |group_path|
+ group_hashes = HashOp::Deep.fetch(grouped_hashes, group_path)
+ group_values = value_paths.map do |value_path|
+ group_value = HashOp::Math.sum_at_path(group_hashes, value_path)
+ { value_path => group_value }
end
- work
+ Hash[[grouping_paths, group_path].transpose].merge(Merge.flat(group_values))
end
- work_hash.values
- end
+ end
module_function :sum_on_groups
# Sum values for the specified hashes at the specified path.
# The values are added to the specified zero (defaults to numeric
# 0), and nil values will be coerced to the zero too.
@@ -74,26 +57,26 @@
# @param path [String]
# @param zero [Object] defaults to [Numeric] 0
#
def sum_at_path(hashes, path, zero = 0)
hashes.inject(zero) do |sum, hash|
- value = HashOp::DeepAccess.fetch(hash, path) || zero
+ value = HashOp::Deep.fetch(hash, path) || zero
sum + value
end
end
module_function :sum_at_path
# @param [Array] hashes array of Hash
# @param [String, Symbol] path to deep value in each hash
def deep_min(hashes, path)
- hashes.map { |hash| HashOp::DeepAccess.fetch hash, path }.min
+ hashes.map { |hash| HashOp::Deep.fetch hash, path }.min
end
module_function :deep_min
# @param [Array] hashes array of Hash
# @param [String, Symbol] path to deep value in each hash
def deep_max(hashes, path)
- hashes.map { |hash| HashOp::DeepAccess.fetch hash, path }.max
+ hashes.map { |hash| HashOp::Deep.fetch hash, path }.max
end
module_function :deep_max
end
end