Last active
November 12, 2019 15:55
-
-
Save rmosolgo/640d599bc1902812e46161b080f5cb05 to your computer and use it in GitHub Desktop.
Calculating "complexity" in a duplication-agnostic way
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| inputs = [ | |
| # These inputs are "like" GraphQL queries because: | |
| # - Some keys are scalars, others are nested hashes | |
| # - Keys may be repeated | |
| # | |
| # Pretend they're like `{ field => complexity }` pairs. | |
| [{ a: 1, b: 1 }], | |
| [{ a: 1, b: 1 }, { b: 1 }], | |
| [{ a: 1, b: 1, c: { d: 1 } }, { c: { d: 1, e: 1 } }] | |
| ] | |
| # For each key in the hash: | |
| # - if it's a scalar and we don't already have its complexity, "calculate" and store the complexity | |
| # - if it's a hash, enter a new accumulator (or re-enter it) and continue analyzing the children | |
| def analyze(hash, acc) | |
| # Visit each field in the hash. | |
| # IRL you would use `ast_field.alias` as the key here | |
| hash.each do |key, value| | |
| if value.is_a?(Hash) | |
| # Continue traversing _into_ hashes, using the previous | |
| # accumulator for this field if there's already one | |
| next_acc = acc[key] ||= { } | |
| analyze(value, next_acc) | |
| else | |
| # "calculate" the complexity for the scalar | |
| acc[key] ||= value | |
| end | |
| end | |
| # Recalculate the total because you might've added new values. | |
| # If you're really tricky, maybe this could be accomplished without a total recalculation. | |
| acc[:__total] = 0 | |
| acc.each do |k, v| | |
| if v.is_a?(Hash) | |
| acc[:__total] += v[:__total] | |
| elsif k != :__total | |
| acc[:__total] += v | |
| end | |
| end | |
| # Return the analyzed complexities, by field name | |
| acc | |
| end | |
| inputs.each do |input| | |
| acc = {} | |
| input.each do |h| | |
| analyze(h, acc) | |
| end | |
| p acc | |
| end | |
| # {:a=>1, :b=>1, :__total=>2} | |
| # {:a=>1, :b=>1, :__total=>2} | |
| # {:a=>1, :b=>1, :c=>{:d=>1, :__total=>2, :e=>1}, :__total=>4} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment