# frozen_string_literal: true module Underpass # Post-query filtering of {Feature} objects by tag properties. # # @example Filter restaurants by cuisine # filter = Underpass::Filter.new(features) # italian = filter.where(cuisine: 'italian') class Filter # Creates a new filter for the given features. # # @param features [Array<Feature>] the features to filter def initialize(features) @features = features end # Returns features whose properties match all given conditions. # # Conditions can be exact values, regular expressions, or arrays of values. # # @param conditions [Hash{Symbol => String, Regexp, Array}] tag conditions to match # @return [Array<Feature>] features matching all conditions # # @example Exact match # filter.where(cuisine: 'italian') # @example Regex match # filter.where(name: /pizza/i) # @example Array inclusion # filter.where(cuisine: ['italian', 'mexican']) def where(conditions = {}) @features.select do |feature| conditions.all? { |key, value| match_condition?(feature.properties[key], value) } end end # Returns features that do not match any of the given conditions. # # @param conditions [Hash{Symbol => String}] tag conditions to reject # @return [Array<Feature>] features not matching any condition def reject(conditions = {}) @features.reject do |feature| conditions.any? { |key, value| feature.properties[key] == value.to_s } end end private def match_condition?(prop_value, condition) case condition when Regexp then prop_value&.match?(condition) when Array then condition.include?(prop_value) else prop_value == condition.to_s end end end end