1

I want to convert the string into an array, I have tried some steps but not getting the desired result.

(:require [clojure.string :as str])

(def stringval "fruit==Mango,fruit==Papaya;veggie==Onion,veggie==Potato")

(defn formatting [strFilters]   
(let [filters (str/split strFilters #";")]
    (for [filter filters]
      (let [eachFilter (str/split filter #",")]
        (for [each eachFilter]
          (let [items (str/split each #"==")]
            items
            )))))) 
(formatting stringval)

I am getting below output

((["fruit" "Mango"] ["fruit" "Papaya"]) (["veggie" "Onion"] ["veggie" "Potato"]))

I want clojure function which returns the below array

Array
(
    [fruit] => Array
        (
            [0] => Mango
            [1] => Papaya
        )

    [veggie] => Array
        (
            [0] => Onion
            [1] => Potato
        )

)
1
  • Do you mean Java array? So the result should have the same structure as the result of (to-array-2d [["Mango" "Papaya"] ["Onion" "Potato"]])? Commented Jan 12, 2023 at 11:29

2 Answers 2

3

You want a list of maps, so you have to turn your current intermediate results into a map. You can do this with group-by and some some post-processing, or you can use merge-with conj if you shape the result from the innermost for in preparation for it. Also note, that for can have :let in it.

(require '[clojure.string :as str])

(def s "fruit==Mango,fruit==Papaya;veggie==Onion,veggie==Potato")

(for [g (str/split s #";")]
  (apply merge-with into
         (for [kv (str/split g #",")
               :let [[k v] (str/split kv #"==")]]
           {k [v]})))
; → ({"fruit" ["Mango" "Papaya"]} {"veggie" ["Onion" "Potato"]})

And in case your target-output there is from PHP or some other language, that got their basic data structures wrong, and you actually just want a map with the keys to arrays of values, you just have to to shift the merge-with into out and you can also split for ; and , one swoop.

(apply merge-with into
       (for [kv (str/split s #"[;,]")
             :let [[k v] (str/split kv #"==")]]
         {k [v]}))
; → {"fruit" ["Mango" "Papaya"], "veggie" ["Onion" "Potato"]}
Sign up to request clarification or add additional context in comments.

1 Comment

Note, that just using split will ignore problems when ;, ,, and == must be allowed for keys and values and some sort of quoting is used. Using a proper parser would be the defensive choice.
2

one more option is to get all the pairs with re-seq and reduce it with grouping:

(->> stringval
     (re-seq #"([^,;].+?)==([^,;$]+)")     
     (reduce (fn [acc [_ k v]] (update acc k conj v)) {}))

;;=> {"fruit" ("Papaya" "Mango"), "veggie" ("Potato" "Onion")}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.