I have data in below format.
'(({:nums {:test number?, :data (1)}})
{:Other ()}
({:nums {:test number?, :data (2)}})
({:nums {:test number?, :data (3 4)}}))
But I would like to get data in below format.
'(({:nums {:test number?, :data (1 2 3 4)}})
{:Other ()})
Tried with merge, union functions, but not worked. Could you please help here as I am beginner to Closure.
Doing tests on below code
(split '(1 2 (3 4 [1 2 3])) {:nums {:test number?}})
=>
((({:nums {:test number?, :data (1)}}) {:Other ()})
(({:nums {:test number?, :data (2)}}) {:Other ()})
(({:nums {:test number?, :data (3 4)}}) {:Other (([1 2 3]))}))
But The target result I am expecting as below
(split '(1 2 (3 4 [1 2 3])) {:nums {:test number?}})
=>
(({:nums {:test number?, :data (1 2 3 4)}})
{:Other ([1 2 3])})
Code used:
(defn test
[list1 filter1]
;(get-in (first (first (split list1 filter1))) [:nums :test])
(first (first (split list1 filter1))))
(defn split [list1 filter_map]
(if (empty? list1)
()
(cons (split_list
(if (sequential? (first list1))
(first list1)
(list (first list1)))
filter_map)
(split (rest list1) filter_map))))
(defn split_list [list1 filter_map]
(let [var_in_filter (remove nil? (in-filter filter_map))
var_out_filter (remove nil? (out-filter filter_map))]
;var_out_filter
(list (in_filter_recur list1 var_in_filter)
;(in_filter_recur list1 var_in_filter)
(hash-map :Other (remove nil?
(out_filter_recur list1 var_out_filter))))))
(defn in_filter_recur [lis in_filt]
(if (empty? in_filt)
nil
(cons (hash-map
(if ((first in_filt) 1)
:nums
;"{:nums {:test number?}"
(if ((first in_filt) 'a)
:syms
(if ((first in_filt) [1])
:vects
'others)))
;(set (merge [:data] (filter (first in_filt) lis))))
(hash-map :test
(if ((first in_filt) 1)
'number?
;"{:nums {:test number?}"
(if ((first in_filt) 'a)
'symbols?
(if ((first in_filt) [1])
'vector?
'others)))
:data (filter (first in_filt) lis)))
(in_filter_recur lis (rest in_filt)))))
(defn out_filter_recur [lis out_filt]
(if (empty? out_filt)
nil
(cons ;(hash-map nil
(if (empty? (filter (first out_filt) lis))
nil
(filter (first out_filt) lis))
(out_filter_recur lis (rest out_filt)))))
(defn out-filter [filt]
(difference
(set
(All-filter
{:nums {:test number?}
:syms {:test symbol?}
:vects {:test vector?}
:other {:test string?}})) (set (in-filter filt))))
(defn in-filter [filt]
(list (when
(and (> (count (str (get-in filt [:nums :test]))) 0)
((get-in filt [:nums :test]) 1))
number?)
(when
(and (> (count (str (get-in filt [:syms :test]))) 0)
((get-in filt [:syms :test]) 'a))
symbol?)
(when
(and (> (count (str (get-in filt [:vects :test]))) 0)
((get-in filt [:vects :test]) [1]))
vector?)))
(defn All-filter [filt]
(list (when
(and (> (count (str (get-in filt [:nums :test]))) 0)
((get-in filt [:nums :test]) 1))
number?)
(when
(and (> (count (str (get-in filt [:syms :test]))) 0)
((get-in filt [:syms :test]) 'a))
symbol?)
(when
(and (> (count (str (get-in filt [:vects :test]))) 0)
((get-in filt [:vects :test]) [1]))
vector?)
(when
(and (> (count (str (get-in filt [:other :test]))) 0)
((get-in filt [:other :test]) "1"))
string?)))
(defn difference
([s1] s1)
([s1 s2]
(if (< (count s1) (count s2))
(reduce (fn [result item]
(if (contains? s2 item)
(disj result item)
result))
s1 s1)
(reduce disj s1 s2)))
([s1 s2 & sets]
(reduce difference s1 (conj sets s2))))
Here's what I came up with, it's kind of a specific data structure, so it's pretty specific code
The first step is to set up the data so that we can work with merge-with
(defn get-data [val]
(as-> val ?
(first ?)
(:nums ?)
(select-keys ? [:data])))
Then the last step is to call merge-with
and put it back together
(def x '(({:nums {:test number?, :data (1)}})
{:Other ()}
({:nums {:test number?, :data (2)}})
({:nums {:test number?, :data (3 4)}}))
(as-> x ?
(map get-data ?)
(apply merge-with concat ?)
(assoc ? :test 'number?)
(list ?)
(list ?)
(conj ? {:Other '()})
(reverse ?))
If you were looking for something more generic, you'll have to come at me with a more generic data structure.
I think what you were looking for is mostly contained in the (apply merge-with concat ?)
line which does most of the work.
This function takes a list of maps and applies the function, in this case concat
to the values in those maps.
See (doc merge-with)
in your REPL for more information.
As a last ditch effort, you may also be interested in the specter clojure library which excels at this sort of deeply nested data transformation.
Hope this helps!