Ari
Ari

Reputation: 4191

Returning Sequence From Function

I've put together the function below. It's supposed to take in a nested (multi-tiered) map and return a sequence of flat maps; however, it currently returns a sequence within a sequence.

Does anyone know why the sequence is being nested within another sequence?

(defn collapse [data & keys-coll]
  (if (map? data)
    (for [[k v] data]
      (collapse v (if (nil? keys-coll)
                    (conj [] k)
                    (conj (into [] keys-coll) k))))
    (hash-map (flatten keys-coll) data)))

(collapse {"a" {2011 [["a" 2011 "dan"] ["a" 2011 "ari"]] 2010 [["a" 2010 "jon"]]}})

Results in:

( ({("a" 2011) [["a" 2011 "dan"] ["a" 2011 "ari"]]}
   {("a" 2010) [["a" 2010 "jon"]]}) )

Expected/Desired result (notice the sequence, NOT a sequence within a sequence as above):

({("a" 2011) [["a" 2011 "dan"] ["a" 2011 "ari"]]}
 {("a" 2010) [["a" 2010 "jon"]]})

Note: The expected result is a sequence of maps; each map is comprised of composite keys and nested vectors.

Upvotes: 1

Views: 145

Answers (1)

Paul
Paul

Reputation: 8172

The reason that you are getting a sequence within another sequence is that for returns a lazy seq. Because it is called every time collapse encounters a map and the map you provide nests two levels deep you're getting sequences nested two levels deep.

Quick fix: put a flatten in front of the for like so:

(defn collapse [data & keys-coll]
  (if (map? data)
    (flatten 
     (for [[k v] data]
       (collapse v (conj keys-coll k))))
    (hash-map (flatten keys-coll) data))

(Note that you can also get rid of the if statement). Maybe not the most elegant solution, but suffering from a brain freeze right now ...

Upvotes: 1

Related Questions