Useful row/map/record related functions.
Useful row/map/record related functions.
(bastardify a-something)
Take something, string it and keywordify it, underscores for hyphens.
DEPRECATED! Consider: camel-snake-kebab.core/->snake_case_keyword
Why?
Underscores are OK for things like H2, hyphens? Not so much.
How?
(bastardify "Account: OPEX") => :account_opex
Take something, string it and keywordify it, underscores for hyphens. DEPRECATED! Consider: camel-snake-kebab.core/->snake_case_keyword Why? Underscores are OK for things like H2, hyphens? Not so much. How? (bastardify "Account: OPEX") => :account_opex
(bespoke-header a-map)
(bespoke-header base-header a-map)
(bespoke-header base-header strict? a-map)
Accepts vector and a map, returns header vector derived from both.
Header consists of base-header and remaining keys from the map, sorted.
If strict: base-header must be a subset of keys in the map, otherwise ExceptionInfo. If not strict then just 'do your best'.
If only given the map - returns vector of keys.
Why?
You want some key columns first, while keeping all the data.
How?
(bespoke-header [:x :y :z] {:state :resting :x 0 :y 0 :z 0}) => [:x :y :z :state] (bespoke-header [:x :y :z :cycle] {:state :resting :x 0 :y 0 :z 0}) => [:x :y :z :cycle :state] (bespoke-header [:x :y :z :cycle] true {:state :resting :x 0 :y 0 :z 0}) => clojure.lang.ExceptionInfo: Missing keys in header?
Accepts vector and a map, returns header vector derived from both. Header consists of base-header and remaining keys from the map, sorted. If strict: base-header must be a subset of keys in the map, otherwise ExceptionInfo. If not strict then just 'do your best'. If only given the map - returns vector of keys. Why? You want some key columns first, while keeping all the data. How? (bespoke-header [:x :y :z] {:state :resting :x 0 :y 0 :z 0}) => [:x :y :z :state] (bespoke-header [:x :y :z :cycle] {:state :resting :x 0 :y 0 :z 0}) => [:x :y :z :cycle :state] (bespoke-header [:x :y :z :cycle] true {:state :resting :x 0 :y 0 :z 0}) => clojure.lang.ExceptionInfo: Missing keys in header?
Compatibility shim for de-recordify, see maps->vecs.
Compatibility shim for de-recordify, see maps->vecs.
(deep-sort map-of-maps)
Take a map of maps, return sorted-map of sorted-maps.
Why?
Sometimes you want to be able to just look at the map and know if a key is there. Ordering keys helps.
How?
(deep-sort {100 :a, 90 {10 :maybe, 9 {:yes :no}}, 80 :b}) => {80 :b, 90 {9 {:yes :no}, 10 :maybe}, 100 :a}
Take a map of maps, return sorted-map of sorted-maps. Why? Sometimes you want to be able to just look at the map and know if a key is there. Ordering keys helps. How? (deep-sort {100 :a, 90 {10 :maybe, 9 {:yes :no}}, 80 :b}) => {80 :b, 90 {9 {:yes :no}, 10 :maybe}, 100 :a}
(default-parallel-n)
Return advised parallel workload. Logical processor count + 2.
Why?
Sometimes you just want the answer.
How?
(default-parallel-n) => 10
Return advised parallel workload. Logical processor count + 2. Why? Sometimes you just want the answer. How? (default-parallel-n) => 10
(field-unpacker delimiter field)
See if field contains a str/char delimiter, if so -- tries to parse as CSV.
Why?
Sometimes your fields have fields. (So many fields, fields for days.)
How?
(field-unpacker , "ala,ma,kota") => ["ala", "ma", "kota"]
See if field contains a str/char delimiter, if so -- tries to parse as CSV. Why? Sometimes your fields have fields. (So many fields, fields for days.) How? (field-unpacker \, "ala,ma,kota") => ["ala", "ma", "kota"]
(fixed-width-split fields)
Accept vector of slice sizes, returns function that will cut String.
Why?
Because somebody thought fixed width data records are a good thing.
How?
((fixed-width-split [4 3 4]) "Ala ma Kota.") => ["Ala " "ma " "Kota"]
Accept vector of slice sizes, returns function that will cut String. Why? Because somebody thought fixed width data records are a good thing. How? ((fixed-width-split [4 3 4]) "Ala ma Kota.") => ["Ala " "ma " "Kota"]
(friendlify a-something)
Take Clojure object and try to make a pretty String from its Class.
Why?
Display function name at runtime, but similar to how it looks in code.
How?
(friendlify friendlify) => "szew.io.util/friendlify"
Take Clojure object and try to make a pretty String from its Class. Why? Display function name at runtime, but similar to how it looks in code. How? (friendlify friendlify) => "szew.io.util/friendlify"
(getter a-key)
(getter a-key default)
Takes key and default value, returns a function that gets it.
Why?
Builtin get takes collection as first argument, this is the other way around.
How?
(mapv (getter :yolo :no) [{:yolo :yes} {:wat? :wat}]) => [:yes :no] (meta (getter :yolo :no)) => {:key :yolo, :default :no} (mapv (getter 0 :no) [[:yes] []]) => [:yes :no] (meta (getter 1 :no)) => {:key 1, :default :no}
Takes key and default value, returns a function that gets it. Why? Builtin get takes collection as first argument, this is the other way around. How? (mapv (getter :yolo :no) [{:yolo :yes} {:wat? :wat}]) => [:yes :no] (meta (getter :yolo :no)) => {:key :yolo, :default :no} (mapv (getter 0 :no) [[:yes] []]) => [:yes :no] (meta (getter 1 :no)) => {:key 1, :default :no}
(juxt-map & keys-fns)
Give keys and values, get a juxt map of keys-values. Hint: zipmap over juxt.
Why?
Maps are bees knees and juxt is just cool.
How?
((juxt-map :+ inc :- dec := identity) 2) => {:+ 3, :- 1, := 2}
Give keys and values, get a juxt map of keys-values. Hint: zipmap over juxt. Why? Maps are bees knees and juxt is just cool. How? ((juxt-map :+ inc :- dec := identity) 2) => {:+ 3, :- 1, := 2}
(keywordify a-something)
Take something, take string of it, then make it into keyword.
DEPRECATED! Consider: camel-snake-kebab.core/->kebab-case
Why?
Sometimes you just need a keyword that looks semi decent.
How?
(keywordify "Account: OPEX") => :account-opex
Take something, take string of it, then make it into keyword. DEPRECATED! Consider: camel-snake-kebab.core/->kebab-case Why? Sometimes you just need a keyword that looks semi decent. How? (keywordify "Account: OPEX") => :account-opex
(map->vec header mapped)
(map->vec defaults header mapped)
Takes header vector and map. Returns vector with meta. Allows defaults.
Why?
Singular version of maps->vecs, with inputs attached as meta.
How? (map->vec [:k1 :k2] {:k1 1, :k2 2}) => [1 2] (map->vec {:kx 100} [:k1 :k2 :kx] {:k1 1, :k2 2}) => [1 2 100] (meta (map->vec {:kx 100} [:k1 :k2 :kx] {:k1 1 :k2 2})) => {:defaults {:kx 100}, :header [:k1 :k2 :kx], :mapped {:k1 1, :k2 2}}
Takes header vector and map. Returns vector with meta. Allows defaults. Why? Singular version of maps->vecs, with inputs attached as meta. How? (map->vec [:k1 :k2] {:k1 1, :k2 2}) => [1 2] (map->vec {:kx 100} [:k1 :k2 :kx] {:k1 1, :k2 2}) => [1 2 100] (meta (map->vec {:kx 100} [:k1 :k2 :kx] {:k1 1 :k2 2})) => {:defaults {:kx 100}, :header [:k1 :k2 :kx], :mapped {:k1 1, :k2 2}}
(maps->vecs a-seq)
(maps->vecs head tails)
(maps->vecs defaults head tails)
Takes header vector and maps, returns seq of vectors.
Vector maps tails over head. Defaults are done by merging before mapping.
Why?
Because maps are so nice, but it's also nice to be able to dump them back.
How?
(maps->vecs [[:k1 :k2] {:k1 1, :k2 2}]) => ([1 2]) (maps->vecs [:k1 :k2] [{:k1 1, :k2 2}]) => ([1 2]) (maps->vecs {:kx 100} [:k1 :k2 :kx] [{:k1 1, :k2 2}]) => ([1 2 100]) (maps->vecs [:k1 :k2] [{:k1 1, :k2 2} {:k1 1, :k2 0}]) => ([1 2] [1 0])
Takes header vector and maps, returns seq of vectors. Vector maps tails over head. Defaults are done by merging before mapping. Why? Because maps are so nice, but it's also nice to be able to dump them back. How? (maps->vecs [[:k1 :k2] {:k1 1, :k2 2}]) => ([1 2]) (maps->vecs [:k1 :k2] [{:k1 1, :k2 2}]) => ([1 2]) (maps->vecs {:kx 100} [:k1 :k2 :kx] [{:k1 1, :k2 2}]) => ([1 2 100]) (maps->vecs [:k1 :k2] [{:k1 1, :k2 2} {:k1 1, :k2 0}]) => ([1 2] [1 0])
(maps-maker)
(maps-maker head tails)
Create maps-maker over two functions of input sequence: head and tails.
Defaults: head is first row as kebab-case-keyword vector, tails is rest.
Why?
Because it's a common scenario. I wrote it too many times by hand.
How?
((maps-maker) [["X" "Y"] [0 0] [1 1] [10 10]]) => ({:x 0 :y 0} {:x 1 :y 1} {:x 10 :y 10})
Create maps-maker over two functions of input sequence: head and tails. Defaults: head is first row as kebab-case-keyword vector, tails is rest. Why? Because it's a common scenario. I wrote it too many times by hand. How? ((maps-maker) [["X" "Y"] [0 0] [1 1] [10 10]]) => ({:x 0 :y 0} {:x 1 :y 1} {:x 10 :y 10})
(ppfilter n p)
(ppfilter n f coll)
Parametrized parallel filter, with max of n threads at once.
Accepts number of threads n, predicate p and a collection. If no collection is provided it produces a stateful transducer.
Why?
The real question is: why no pfilter?!
How?
(vec (filter odd? [1 2 3])) => [1 3] (vec (ppfilter 1 odd? [1 2 3])) => [1 3]
Parametrized parallel filter, with max of n threads at once. Accepts number of threads n, predicate p and a collection. If no collection is provided it produces a stateful transducer. Why? The real question is: why no pfilter?! How? (vec (filter odd? [1 2 3])) => [1 3] (vec (ppfilter 1 odd? [1 2 3])) => [1 3]
(ppmap n f)
(ppmap n f coll)
(ppmap n f coll & colls)
Parametrized parallel map. Like pmap, but with max of n threads at once.
Accepts number of threads n, function f and collections. If no collections are provided it produces a stateful transducer.
Why?
Better pmap for multicore world.
How?
(vec (map inc [1 2 3])) => [2 3 4] (vec (ppmap 1 inc [1 2 3])) => [2 3 4]
Parametrized parallel map. Like pmap, but with max of n threads at once. Accepts number of threads n, function f and collections. If no collections are provided it produces a stateful transducer. Why? Better pmap for multicore world. How? (vec (map inc [1 2 3])) => [2 3 4] (vec (ppmap 1 inc [1 2 3])) => [2 3 4]
(ppmapcat n f)
(ppmapcat n f & colls)
Parametrized parallel mapcat, with max of n threads at once for mapping. If no collection is provided ir produces a stateful transducer.
Accepts number of threads n, function f and a collection.
Why?
Easy once ppmap is defined so why not?
How?
(mapcat (juxt dec identity inc) [1 2 3 4]) => (0 1 2 1 2 3 2 3 4 3 4 5) (ppmapcat 4 (juxt dec identity inc) [1 2 3 4]) => (0 1 2 1 2 3 2 3 4 3 4 5)
Parametrized parallel mapcat, with max of n threads at once for mapping. If no collection is provided ir produces a stateful transducer. Accepts number of threads n, function f and a collection. Why? Easy once ppmap is defined so why not? How? (mapcat (juxt dec identity inc) [1 2 3 4]) => (0 1 2 1 2 3 2 3 4 3 4 5) (ppmapcat 4 (juxt dec identity inc) [1 2 3 4]) => (0 1 2 1 2 3 2 3 4 3 4 5)
Compatibility shim for recordify, see vecs->maps.
Compatibility shim for recordify, see vecs->maps.
(roll-in seq-of-seqs)
(roll-in agg seq-of-seqs)
Take sequence of sequences, last item is value, butlast items are the key. Return map of maps.
If agg callable is given -- it's used with update-in, otherwise entries action is assoc-in.
Why?
I just like maps.
How?
(roll-in [[:a :b 3] [:a :c 4] [:x :z 0]]) => {:a {:b 3 :c 4} :x {:z 0}} (roll-in (fnil + 0) [[:a :b 3] [:a :c 4] [:x :z 0] [:a :c 2]]) => {:a {:b 3 :c 6} :x {:z 0}}
Take sequence of sequences, last item is value, butlast items are the key. Return map of maps. If agg callable is given -- it's used with update-in, otherwise entries action is assoc-in. Why? I just like maps. How? (roll-in [[:a :b 3] [:a :c 4] [:x :z 0]]) => {:a {:b 3 :c 4} :x {:z 0}} (roll-in (fnil + 0) [[:a :b 3] [:a :c 4] [:x :z 0] [:a :c 2]]) => {:a {:b 3 :c 6} :x {:z 0}}
(roll-out map-of-maps)
(roll-out stop-at? map-of-maps)
Take a map of maps, return sequence of vectors.
Why?
I like maps, but vectors are also pretty neat.
How?
(set (roll-out {:a {:b 3 :c 4} :x {:z 0}})) ;; because ordering. => #{[:a :b 3] [:a :c 4] [:x :z 0]} (set (roll-out #(contains? % :b) {:a {:b 3 :c 4} :x {:z 0}})) => #{[:a {:b 3 :c 4}] [:x :z 0]}
Take a map of maps, return sequence of vectors. Why? I like maps, but vectors are also pretty neat. How? (set (roll-out {:a {:b 3 :c 4} :x {:z 0}})) ;; because ordering. => #{[:a :b 3] [:a :c 4] [:x :z 0]} (set (roll-out #(contains? % :b) {:a {:b 3 :c 4} :x {:z 0}})) => #{[:a {:b 3 :c 4}] [:x :z 0]}
(row-adjuster default-row)
Creates a function that will return vectors of same length as default-row. Missing columns will be filled by defaults. Extra columns dropped.
Why?
Because *SV does not have to be well formed, numbers of column may vary.
How?
((row-adjuster [1 2 3]) [:x]) => [:x 2 3] ((row-adjuster [1 2 3]) [:1 :2 :3 :4]) => [:1 :2 :3]
Creates a function that will return vectors of same length as default-row. Missing columns will be filled by defaults. Extra columns dropped. Why? Because *SV does not have to be well formed, numbers of column may vary. How? ((row-adjuster [1 2 3]) [:x]) => [:x 2 3] ((row-adjuster [1 2 3]) [:1 :2 :3 :4]) => [:1 :2 :3]
(row-field-unpacker delimiter a-row)
Run field unpacker over entire row.
Why?
Partial it away and apply to nested CSV/TSV stuff.
How?
(row-field-unpacker , ["xnay" "ala,ma,kota" "unpackey") => ["xnay" ["ala" "ma" "kota"] "unpackey"]
Run field unpacker over entire row. Why? Partial it away and apply to nested CSV/TSV stuff. How? (row-field-unpacker \, ["xnay" "ala,ma,kota" "unpackey") => ["xnay" ["ala" "ma" "kota"] "unpackey"]
(vec->map header values)
(vec->map defaults header values)
Takes header and values vector, zipmaps, adds metadata. Allows defaults.
Why?
Singular operation for vecs->maps, with inputs attached as meta.
How? (vec->map [:k1 :k2] [1 2]) => {:k1 1, :k2 2} (vec->map {:kx 100} [:k1 :k2] [1 2]) => {:kx 100, :k1 1, :k2 2} (meta (vec->map {:kx 100} [:k1 :k2] [1 2])) => {:defaults {:kx 100}, :header [:k1 :k2], :values [1 2]}
Takes header and values vector, zipmaps, adds metadata. Allows defaults. Why? Singular operation for vecs->maps, with inputs attached as meta. How? (vec->map [:k1 :k2] [1 2]) => {:k1 1, :k2 2} (vec->map {:kx 100} [:k1 :k2] [1 2]) => {:kx 100, :k1 1, :k2 2} (meta (vec->map {:kx 100} [:k1 :k2] [1 2])) => {:defaults {:kx 100}, :header [:k1 :k2], :values [1 2]}
(vecs->maps a-seq)
(vecs->maps head tails)
(vecs->maps defaults head tails)
Takes header vector and tails, returns seq of maps.
Zipmaps head with tails. Merges with defaults, doing nil substitution.
Why?
Maps are friendlier then vectors.
How?
(vecs->maps [[:k1 :k2] [1 2] [3 4]]) => ({:k1 1, :k2 2}, {:k1 3 :k2 4}) (vecs->maps [:k1 :k2] [[1 2] [3 4]]) => ({:k1 1, :k2 2}, {:k1 3 :k2 4}) (let [s [[:a :b] [1 2] [3 4]]] (vecs->maps (first s) (rest s))) => ({:a 1, :b 2}, {:a 3, :b 4}) (let [d {:x 100, :b 9} s [[:a :b] [1 nil] [3 4]]] (vecs->maps d (first s) (rest s))) => ({:a 1 :b 9 :x 100} {:a 3 :b 4 :x 100})
Takes header vector and tails, returns seq of maps. Zipmaps head with tails. Merges with defaults, doing nil substitution. Why? Maps are friendlier then vectors. How? (vecs->maps [[:k1 :k2] [1 2] [3 4]]) => ({:k1 1, :k2 2}, {:k1 3 :k2 4}) (vecs->maps [:k1 :k2] [[1 2] [3 4]]) => ({:k1 1, :k2 2}, {:k1 3 :k2 4}) (let [s [[:a :b] [1 2] [3 4]]] (vecs->maps (first s) (rest s))) => ({:a 1, :b 2}, {:a 3, :b 4}) (let [d {:x 100, :b 9} s [[:a :b] [1 nil] [3 4]]] (vecs->maps d (first s) (rest s))) => ({:a 1 :b 9 :x 100} {:a 3 :b 4 :x 100})
(vecs-maker)
(vecs-maker defaults)
(vecs-maker defaults header-prep row-prep)
Accepts defaults and two output producing functions of header and row.
By default header-prep is vector of SCREAMING_SNAKE_CASE_STRING.
By default row-prep is a vector of string with nil becoming "NULL".
Bespoke header based on first records, so they better be uniform!
Why?
Quick and dirty dumps!
How? ((vecs-maker) [[:x :y :z] [{:x 0 :y 0} {:x 10 :y 10}]]) => (["X" "Y" "Z"] ["0" "0" "NULL"] ["10" "10" "NULL"]) ((vecs-maker {:z 0}) [[:x :y :z] [{:x 0 :y 0} {:x 10 :y 10}]]) => (["X" "Y" "Z"] ["0" "0" "0"] ["10" "10" "0"]) ((vecs-maker {:z 0} identity identity) [[:x :y :z] [{:x 0 :y 0} {:x 10 :y 10}]]) => ([:x :y :z] [0 0 0] [10 10 0]) ((vecs-maker nil identity identity) [[:x :y :z] [{:x 0 :y 0} {:x 10 :y 10}]]) => ([:x :y :z] [0 0 nil] [10 10 nil])
Accepts defaults and two output producing functions of header and row. By default header-prep is vector of SCREAMING_SNAKE_CASE_STRING. By default row-prep is a vector of string with nil becoming "NULL". Bespoke header based on first records, so they better be uniform! Why? Quick and dirty dumps! How? ((vecs-maker) [[:x :y :z] [{:x 0 :y 0} {:x 10 :y 10}]]) => (["X" "Y" "Z"] ["0" "0" "NULL"] ["10" "10" "NULL"]) ((vecs-maker {:z 0}) [[:x :y :z] [{:x 0 :y 0} {:x 10 :y 10}]]) => (["X" "Y" "Z"] ["0" "0" "0"] ["10" "10" "0"]) ((vecs-maker {:z 0} identity identity) [[:x :y :z] [{:x 0 :y 0} {:x 10 :y 10}]]) => ([:x :y :z] [0 0 0] [10 10 0]) ((vecs-maker nil identity identity) [[:x :y :z] [{:x 0 :y 0} {:x 10 :y 10}]]) => ([:x :y :z] [0 0 nil] [10 10 nil])
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close