Skip to content

Instantly share code, notes, and snippets.

@pingles
Created November 2, 2010 20:06
Show Gist options
  • Save pingles/660205 to your computer and use it in GitHub Desktop.
Save pingles/660205 to your computer and use it in GitHub Desktop.
(ns tree
(:require [clojure.contrib.string :as str]))
(def postcodes '({:postcode "AL" :region-id 10}
{:postcode "AB" :region-id 12}
{:postcode "AL4" :region-id 10}))
(defn next-record
[record]
{:postcode (apply str (rest (:postcode record)))
:region-id (:region-id record)})
(defn record-to-tree
([record] (record-to-tree record {}))
([record tree]
(let [postcode (:postcode record)
region-id (:region-id record)]
(if (nil? (seq postcode))
tree
(assoc tree
(keyword (str (first postcode)))
(postcode-to-tree (next-record record)
{:region-id region-id}))))))
(defn merge-tree
[tree subtree]
(let [first-key (first (keys subtree))]
(if (contains? tree first-key)
(assoc tree first-key (merge-tree (first-key tree) (first-key subtree)))
(assoc tree first-key (first-key subtree)))))
;; tree=> (merge-tree {:a {:b 2}} {:a {:c 3}})
;; {:a {:c 3, :b 2}}
;; tree=> (reduce merge-tree {} (map record-to-tree postcodes))
;; {:A {:B {:region-id 12}, :L {:4 {:region-id 10}, :region-id 10},
;; :region-id 10}}
(def results (reduce merge-tree {} (map record-to-tree postcodes)))
(defn lookup-postcode
[results postcode]
(if (nil? (seq postcode))
(:region-id results)
(recur ((keyword (str (first postcode))) results)
(rest postcode))))
;; tree=> (lookup-postcode results "AB")
;; 12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment