title: Filtering a hashmap by value in Clojure when values have compound data
body: <p>I'm trying to teach myself Clojure.</p>
  
  <p>For a work-related project (to state the obvious, I'm not a professional programmer), I'm trying to combine a bunch of spreadsheets. The spreadsheets have comments that relate to financial transactions. Multiple comments (including across spreadsheets) can refer to the same transaction; each transaction has a unique serial number. I am therefore using the following data structure to represent the spreadsheets: </p>
  
  <pre><code>(def ss { :123 '([ "comment 1" "comment 2" ]
                   [ "comment 3" "comment 4" ]
                   [ "comment 5" ]),
            :456 '([ "happy days" "are here" ]
                   [ "again" ])})
  </code></pre>
  
  <p>This might be created from the following two spreadsheets:</p>
  
  <pre><code>+------------+------------+-----------+
  | Trans. No. |   Cmt. A   |  Cmt. B   |
  +------------+------------+-----------+
  |        123 | comment 1  | comment 2 |
  |        456 | happy days | are here  |
  |        123 | comment 3  | comment 4 |
  +------------+------------+-----------+
  
  +-----------------+------------+
  | Analyst Comment | Trans. No. |
  +-----------------+------------+
  | comment 5       |        123 |
  | again           |        456 |
  +-----------------+------------+
  </code></pre>
  
  <p>I have successfully written functions to create this data structure given a directory full of CSVs. I want to write two further functions:</p>
  
  <pre><code>;; FUNCTION 1 ==========================================================
  ;; Regex Spreadsheet -&gt; Spreadsheet     ; "Spreadsheet" is like ss above 
  ;; Produces a Spreadsheet with ALL comments per transaction if ANY
  ;;     value matches the regex
  
  ; (defn filter-all [regex my-ss]     {}) ; stub
  
  (defn filter-all [regex my-ss]           ; template
    (... my-ss))
  
  (deftest filter-all-tests
    (is (= (filter-all #"1" ss) 
           { :123 '([ "comment 1" "comment 2" ]
                    [ "comment 3" "comment 4" ]
                    [ "comment 5" ]) })))
  
  ;; FUNCTION 2 ==========================================================
  ;; Regex Spreadsheet -&gt; Spreadsheet     ; "Spreadsheet" is like ss above 
  ;; Produces a Spreadsheet with each transaction number that has at least
  ;;     one comment that matches the regex, but ONLY those comments that 
  ;;     match the regex
  
  ; (defn filter-matches [regex my-ss] {}) ; stub
  
  (defn filter-matches [regex my-ss]       ; template
    (... my-ss))
  
  (deftest filter-matches-tests
    (is (= (filter-matches #"1" ss) 
           { :123 '([ "comment 1" ]) })))
  </code></pre>
  
  <p>What I don't understand is the best way to get the regex far enough down into the <code>vals</code> for each <code>key</code>, given that they are strings nested inside vectors nested inside lists. I have tried using <code>filter</code> with nested <code>apply</code>s or <code>map</code>s, but I'm confusing myself with the syntax and even if it works I don't know how to hang on to the <code>keys</code> in order to build up a new hashmap.</p>
  
  <p>I have also tried using destructuring within the <code>filter</code> function, but there too I'm confusing myself and I also think I have to "lift" the functions across the nested data (I think that's the term&mdash;like applicatives and monads in Haskell).</p>
  
  <p>Can somebody please suggest the best approach to filtering this data structure? As a separate matter, I would be glad to have feedback on whether this is a sensible data structure for my purposes, but I would like to learn how to solve this problem as it currently exists, if only for learning purposes.</p>
  
  <p>Thanks much.</p>