Search code examples
clojure

How to push new element in map under case statement inside loop in clojure


I am writing clojure code where I am using case statement inside the loop and I want each data in a single map, below code I have written and what ever data I am getting in print statement I want all that in a single map

  (defn formatGa4DimensionFilters [stringData]
    (def abc {:orGroup {:expressions []}})
      (doseq [semiFormat (str/split stringData #";")]
        (if (str/includes? semiFormat ",")
          (do (doseq [commaFormat (str/split semiFormat #",")]
                (def filterSymbol (get-symbol-for-filter commaFormat))
              (case filterSymbol
                "=~" (let [[key value] (str/split commaFormat #"=~")]
                       (println {:filter {:fieldName key :stringFilter {:values value :matchType "PARTIAL_REGEXP"}}}))
                "!~" (let [[key value] (str/split commaFormat #"!~")]
                       (println {:notExpression {:filter {:fieldName key :stringFilter {:values value :matchType "PARTIAL_REGEXP"}}}}))
                "=@" (let [[key value] (str/split commaFormat #"=@")]
                       (println {:filter {:fieldName key :stringFilter {:values value :matchType "CONTAINS"}}}))
                "!@" (let [[key value] (str/split commaFormat #"!@")]
                       (println {:notExpression {:filter {:fieldName key :stringFilter {:values value :matchType "CONTAINS"}}}}))
                "==" (let [[key value] (str/split commaFormat #"==")]
                       (println {:filter {:fieldName key :stringFilter {:values value :matchType "EXACT"}}}))
                "!=" (let [[key value] (str/split commaFormat #"!=")]
                       (println {:notExpression {:filter {:fieldName key :stringFilter {:values value :matchType "EXACT"}}}}))
                (println "x is not defined"))))
          (do (def symbolFilter2 (get-symbol-for-filter semiFormat))
              (case symbolFilter2
                "=~" (let [[key value] (str/split semiFormat #"=~")]
                       (println {:filter {:fieldName key :stringFilter {:values value :matchType "PARTIAL_REGEXP"}}}))
                "!~" (let [[key value] (str/split semiFormat #"!~")]
                       (println {:notExpression {:filter {:fieldName key :stringFilter {:values value :matchType "PARTIAL_REGEXP"}}}}))
                "=@" (let [[key value] (str/split semiFormat #"=@")]
                       (println {:filter {:fieldName key :stringFilter {:values value :matchType "CONTAINS"}}}))
                "!@" (let [[key value] (str/split semiFormat #"!@")]
                       (println {:notExpression {:filter {:fieldName key :stringFilter {:values value :matchType "CONTAINS"}}}}))
                "==" (let [[key value] (str/split semiFormat #"==")]
                       (println {:filter {:fieldName key :stringFilter {:values value :matchType "EXACT"}}}))
                "!=" (let [[key value] (str/split semiFormat #"!=")]
                       (println {:notExpression {:filter {:fieldName key :stringFilter {:values value :matchType "EXACT"}}}}))
                (println "x is not defined"))))))

  (defn ga4DimensionFilters [semiFormat] 
    (for [commaFormat (str/split semiFormat #",")]
      (def filterSymbol (get-symbol-for-filter commaFormat))
      )
    filterSymbol
    )
  
(defn get-symbol-for-filter [string]
  (doseq [ga4-filter-symbols ["=~","!~","=@","!@","==","!="]]
    (def match-found (str/includes? string ga4-filter-symbols))
    (if (boolean match-found)
      (def filterMatch ga4-filter-symbols)))
  filterMatch) 

(def stringData "ga:city==San Jose,ga:city==Bengaluru;ga:country=~India;ga:country!~United States;ga:state==delhi,ga:state==goa")

(formatGa4DimensionFilters stringData)

current print data

{:filter {:fieldName ga:city, :stringFilter {:values San Jose, :matchType EXACT}}}
{:filter {:fieldName ga:city, :stringFilter {:values Bengaluru, :matchType EXACT}}}
{:filter {:fieldName ga:country, :stringFilter {:values India, :matchType PARTIAL_REGEXP}}}
{:notExpression {:filter {:fieldName ga:country, :stringFilter {:values United States, :matchType PARTIAL_REGEXP}}}}
{:filter {:fieldName ga:state, :stringFilter {:values delhi, :matchType EXACT}}}
{:filter {:fieldName ga:state, :stringFilter {:values goa, :matchType EXACT}}}
nil

expected output

{:andGroup
 {:expressions
  [{:orGroup {:expressions [{:filter {:fieldName "ga:city", :stringFilter {:values "San Jose", :matchType "EXACT"}}}
{:filter {:fieldName "ga:city", :stringFilter {:values "Bengaluru", :matchType "EXACT"}}}]}} 
   [{:filter {:fieldName "ga:country", :stringFilter {:values "India", :matchType "PARTIAL_REGEXP"}}}]
   [{:notExpression
     {:filter {:fieldName "ga:country", :stringFilter {:values "United States", :matchType "PARTIAL_REGEXP"}}}}]
   {:orGroup {:expressions [{:filter {:fieldName "ga:state", :stringFilter {:values "delhi", :matchType "EXACT"}}}
{:filter {:fieldName "ga:state", :stringFilter {:values "goa", :matchType "EXACT"}}}]}}
]}}

All should be in single map {:expressions ... }


Solution

  • I think you need something like this:

    (def match-map {"==" "EXACT"
                    "=~" "PARTIAL_REGEXP"
                    "=@" "CONTAINS"})
    
    (defn parse-entry [s]
      (let [[_ label op name'] (re-matches #"(.*)(==|=~|=@)(.*)" s)]
        {:filter {:fieldName    label
                   :stringFilter {:values     name'
                                   :matchType (match-map op)}}}))
    
    (defn parse-str [s]
      (condp #(str/includes? %2 %1) s
        ";" {:andGroup {:expressions (->> (str/split s #";")
                                          (mapv parse-str)
                                          (mapv #(if (= (key (first %)) :orGroup) % [%])))}}
        "," {:orGroup {:expressions (mapv parse-str (str/split s #","))}}
        "!" {:notExpression (parse-entry (str/replace s #"!" "="))}
        (parse-entry s)))
    

    Example call:

    (parse-str "ga:city==San Jose,ga:city==Bengaluru;ga:country=~India;ga:country!~United States;ga:state==delhi,ga:state==goa")
    =>
    {:andGroup {:expressions [{:orGroup {:expressions [{:filter {:fieldName "ga:city",
                                                                 :stringFilter {:values "San Jose", :matchType "EXACT"}}}
                                                       {:filter {:fieldName "ga:city",
                                                                 :stringFilter {:values "Bengaluru", :matchType "EXACT"}}}]}}
                              [{:filter {:fieldName "ga:country",
                                         :stringFilter {:values "India", :matchType "PARTIAL_REGEXP"}}}]
                              [{:notExpression {:filter {:fieldName "ga:country",
                                                         :stringFilter {:values "United States",
                                                                        :matchType "PARTIAL_REGEXP"}}}}]
                              {:orGroup {:expressions [{:filter {:fieldName "ga:state",
                                                                 :stringFilter {:values "delhi", :matchType "EXACT"}}}
                                                       {:filter {:fieldName "ga:state",
                                                                 :stringFilter {:values "goa", :matchType "EXACT"}}}]}}]}}