# How can I simplify the following to avoid sequence of maps?

Given the following code, I have written a for loop that returns a key and value (0 or 1) of file names passed. 1 means present, and 0 means not present.

Is there a way to construct a flat map without having to use into?

(defn kind-stat
[filename expected-type]
(let [f (File. filename)
s (cond
(.isFile f)      "f"
(.isDirectory f) "d"
(.exists f)      "o"
:else            "n" )]

(if (= expected-type s)
0
1)))

(defn look-for
[filename expected-type]
(let [find-status (kind-stat filename expected-type)]
find-status))

(defn all-files-present?
"Takes a list of real file names, and returns a sequence of maps
indicating the file name and its availability status 1 for present
and 0 for not present. Please note look-for returns 0 for success,
so its return logic needs to be reversed for the return sequence
of maps."
[file-seq]
(for [fnam file-seq
:let [stat-map {(keyword fnam)
(if (= (look-for fnam "f") 0)
1
0)}]]
stat-map))

(into {}
(all-files-present? '("Makefile" "build.sh" "real-estate.csv")))

{:Makefile 1, :build.sh 1, :real-estate.csv 0}

-

## migrated from programmers.stackexchange.comDec 27 '12 at 17:48

This question came from our site for professional programmers interested in conceptual questions about software development.

I agree, this belongs on codereview. Though I would get rid of your let and if, and make them one whole, and have expected type be the function that accepts f so instead of f, d, o, h, you actually hand it .isFile .isDirectory .exists. That's the critique I would give on code review in my immediate albeit small review. Also I would return instead of 1 or 0 in the sequence, make it the closure to execute to find out if it's present, since it's presence may be transient and can then be checked as needed. –  Jimmy Hoffa Dec 27 '12 at 17:28
What is the purpose of this code? Do you want to know if all files are present, or if each file is present? If it's an all or nothing, you just need to do a reduce with the kind-stat returning true/false and an and –  Jimmy Hoffa Dec 27 '12 at 17:55

You could use zipmap:

(defn all-files-present?
[file-seq]
(let [f  #(bit-flip (look-for % "f") 0)]
(zipmap (map keyword file-seq) (map f file-seq))))

(defn all-files-present?
[file-seq]
(let [f  #(bit-flip (look-for % "f") 0)]
(into {} (map (juxt keyword f) file-seq))))


Note that I use bit-flip instead of the if to flip 1<->0.

It would be nicer if kind-stat would just return a boolen value, so you would simply use

(defn kind-stat
[filename expected-type]
(let [f (File. filename)]
(= expected-type
(cond
(.isFile f)       "f"
(.isDirectory f)  "d"
(.exists f)       "o"
:else            "n"))))

(defn all-files-present?
[file-seq]
(let [f  #(if (kind-stat % "f") 1 0)]
(into {} (map (juxt keyword f) file-seq))))


I removed look-for, since it is virtually useless.

-