Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EPB-11376 refactor deep_find and deep_find_parent logic methods #3

Merged
merged 2 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/push_to_branch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
ruby-version: ['2.7', '3.0', '3.1', head]
ruby-version: ['2.7', '3.0', '3.1', '3.2', head]

steps:
- uses: actions/checkout@v3
Expand Down
16 changes: 10 additions & 6 deletions lib/hash_miner/hash.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Hash
#
# @return [Boolean] whether the key was found
def deep_contains?(key:, hash: self)
return nil unless hash.is_a? Hash
return false unless hash.is_a? Hash
return true if hash.include? key

hash.filter_map do |_k, v|
Expand Down Expand Up @@ -245,37 +245,41 @@ def deep_remove_logic_parent(hash:, key:, parent:)
end

def deep_find_logic(hash:, key:)
hash.filter_map do |k, v|
results = hash.map do |k, v|
if k.eql? key
v
elsif v.is_a?(Hash)
deep_find_logic(hash: v, key: key)
elsif v.is_a?(Array)
[v.filter_map do |item|
[v.map do |item|
deep_find_logic(hash: item, key: key) if item.is_a?(Hash) && item.deep_contains?(key: key)
end]
end
end.flatten

results.all?(nil) ? results.uniq : results.compact
end

def deep_find_parent_logic(hash:, key:, parent:)
hash.filter_map do |k, v|
results = hash.map do |k, v|
if (parent.is_a?(Array) && parent.include?(k)) || parent.eql?(k)
case v
when Hash
deep_find_logic(key: key, hash: v)
when Array
[v.filter_map do |item|
[v.map do |item|
deep_find_logic(key: key, hash: item) if item.is_a?(Hash) && item.deep_contains?(key: key)
end]
end
elsif v.is_a?(Hash) && v.deep_contains?(key: key)
deep_find_parent_logic(hash: v, key: key, parent: parent)
elsif v.is_a?(Array)
[v.filter_map do |item|
[v.map do |item|
deep_find_parent_logic(hash: item, key: key, parent: parent) if item.is_a?(Hash) && item.deep_contains?(key: key)
end]
end
end.flatten

results.all?(nil) ? results.uniq : results.compact
end
end
2 changes: 1 addition & 1 deletion lib/hash_miner/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module HashMiner
VERSION = '1.1.1'
VERSION = '1.1.2'
end
34 changes: 24 additions & 10 deletions spec/hash_miner_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@

RSpec.describe HashMiner do
before(:example) do
@nasty_hash = { my: { super: { duper: { deeply: 'nested hash',
is: [{ duper: 'gross', random: nil }, 'a', 1, nil] } },
hey: { duper: :a, blah: '', foo: [nil] },
deeply: [{ nested: 'hash' }] } }
@nasty_hash = { my:
{ super:
{ duper:
{ deeply: 'nested hash', is: [{ duper: 'gross', random: nil }, 'a', 1, nil] } },
hey: { duper: :a, blah: '', foo: [nil] },
test: nil,
not_true: { my_false_key: false },
deeply: [{ nested: 'hash' }] },
more_deeplyer: { test: nil } }
end

it 'has a version number' do
Expand All @@ -15,26 +20,28 @@
context ' deep_contains?' do
it 'returns true when key found' do
expect(@nasty_hash.deep_contains?(key: :foo)).to be true
expect(@nasty_hash.deep_contains?(key: :my_false_key)).to be true
end
it 'returns false when key found' do
it 'returns false when key not found' do
expect(@nasty_hash.deep_contains?(key: [:foo])).to be false
expect(@nasty_hash.deep_contains?(key: 'foo')).to be false
expect(@nasty_hash.deep_contains?(key: nil)).to be false
end

it 'returns nil when not a Hash object' do
expect(@nasty_hash.deep_contains?(key: nil, hash: [])).to be nil
expect(@nasty_hash.deep_contains?(key: nil, hash: 'a')).to be nil
it 'returns false when not a Hash object' do
expect(@nasty_hash.deep_contains?(key: nil, hash: [])).to be false
expect(@nasty_hash.deep_contains?(key: nil, hash: 'a')).to be false
end
end

context 'deep_count' do
it 'returns the count when key found' do
expect(@nasty_hash.deep_count(key: :foo)).to eq 1
expect(@nasty_hash.deep_count(key: :duper)).to eq 3
expect(@nasty_hash.deep_count(key: :my_false_key)).to eq 1
end

it 'returns 0 when key found' do
it 'returns 0 when key not found' do
expect(@nasty_hash.deep_count(key: [:foo])).to eq 0
expect(@nasty_hash.deep_count(key: 'foo')).to eq 0
expect(@nasty_hash.deep_count(key: nil)).to eq 0
Expand All @@ -55,12 +62,15 @@
])
expect(@nasty_hash.deep_find(key: :deeply)).to eq(['nested hash', { nested: 'hash' }])
expect(@nasty_hash.deep_find(key: :nested)).to eq(['hash'])
expect(@nasty_hash.deep_find(key: :not_true)).to eq([{ my_false_key: false }])
expect(@nasty_hash.deep_find(key: :my_false_key)).to eq([false])
end

it 'returns nil when key not found' do
expect(@nasty_hash.deep_find(key: [:foo])).to be nil
expect(@nasty_hash.deep_find(key: 'foo')).to be nil
expect(@nasty_hash.deep_find(key: nil)).to be nil
expect(@nasty_hash.deep_find(key: 'does_not_exist')).to be nil
end

it 'returns nil when not a Hash object' do
Expand All @@ -71,11 +81,14 @@
it 'can be scoped with a parent key' do
expect(@nasty_hash.deep_find(key: :duper, parent: :hey)).to eq([:a])
expect(@nasty_hash.deep_find(key: :duper, parent: [:hey])).to eq([:a])
expect(@nasty_hash.deep_find(key: :my_false_key, parent: :not_true)).to eq([false])
expect(@nasty_hash.deep_find(key: :duper,
parent: %i[hey
super])).to eq([
{ deeply: 'nested hash',
is: [{ duper: 'gross', random: nil }, 'a', 1, nil] }, :a
is: [
{ duper: 'gross', random: nil }, 'a', 1, nil
] }, :a
])
end

Expand All @@ -100,6 +113,7 @@
is: [{ duper: 'gross' }, 'a', 1,
nil] } },
hey: { duper: :a, foo: [nil] },
not_true: { my_false_key: false },
deeply: [{ nested: 'hash' }] } })
end
end
Expand Down
Loading