Skip to content

Instantly share code, notes, and snippets.

@jjttjj
Created April 11, 2018 04:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jjttjj/926b60731ffd87e6556ec5cc47d8cc61 to your computer and use it in GitHub Desktop.
Save jjttjj/926b60731ffd87e6556ec5cc47d8cc61 to your computer and use it in GitHub Desktop.
(defn zipmap+
"Like zipmap, except `tags` can contain the following:
keywords: treated like zipmap
A vector with a boolean value for it's first element:
the boolean dictates weather the rest of the values in the vector should put
into the parent map and processed.
A vector containing a function f followed by a single keyword k:
The value at this point is parsed as an integer X, and the function applied to
it, to result in integer Y. Y items are collected from the input vals in a sequence
and assoc'ed with keyword k in the resulting map"
[keys vals]
(loop [result {}
tags (seq keys)
vs (seq vals)]
(if (and tags vs)
(let [tag (first tags)
v (first vs)]
(cond
(keyword? tag) (recur (assoc result tag (first vs))
(next tags)
(next vs))
;;include?
(and (vector? tag) (true? (first tag)))
(recur result
(concat (next tag) (next tags))
vs)
;;exclude?
(and (vector? tag) (false? (first tag)))
(recur result (next tags) vs)
(and (vector? tag) (fn? (first tag)))
(let [f (first tag)
n (f (Long/parseLong v))
[taken remaining] ((juxt take drop) n (rest vs))]
(recur (assoc result (second tag) taken)
(next tags)
remaining))
:else (throw (ex-info "unrecognized input"
{:tag tag :value v}))))
result)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment