def filter!(keys, replacement: "[FILTERED]")
      should_replace = lambda do |key|
        replace = false
        keys.each do |k|
          break if replace
          replace = k.is_a?(Regexp) ? key.to_s =~ k : key.to_s == k.to_s
        end
        replace
      end

      copied_object.each do |key, value|
        if value.is_a?(Footing::Hash)
          value.filter!(keys, replacement: replacement)
        elsif value.is_a?(::Array)
          value.each do |val|
            if val.is_a?(Footing::Hash)
              val.filter!(keys, replacement: replacement)
            end
          end
        else
          value = replacement if should_replace.call(key)
          self[key] = value
        end
      end

      self
    end
def filter!(keys, replacement: "[FILTERED]")
      should_replace = lambda do |key|
        replace = false
        keys.each do |k|
          break if replace
          replace = k.is_a?(Regexp) ? key.to_s =~ k : key.to_s == k.to_s
        end
        replace
      end

      copied_object.each do |key, value|
        if value.is_a?(Footing::Hash)
          value.filter!(keys, replacement: replacement)
        elsif value.is_a?(::Array)
          value.each do |val|
            if val.is_a?(Footing::Hash)
              val.filter!(keys, replacement: replacement)
            end
          end
        else
          value = replacement if should_replace.call(key)
          self[key] = value
        end
      end

      self
    end
Recursively filters the values for the specified keys in place.
 IMPORTANT: This mutates the copied_object.

 @param keys [Array<Symbol,String,Regexp>] The keys to filter
 @param replacement [Object] The replacement value to use
 @return [Footing::Hash] Returns self