Reputation: 136613
I guess I need some eyeballs on this to make some sense of this
(println record)
(println (keys record) " - " (class record) " : " (:TradeId record) (:Stock record))
(doall (map #(println "Key " % "Value " (% record)) (keys record)))
Output:
{:Stock ATT, :AccountId 1, :TradeId 37, :Qty 100, :Price 117, :Date 2011-02-24T18:30:00.000Z, :Notes SPLIT 1:10, :Type B, :Brokerage 81.12}
(:Stock :AccountId :TradeId :Qty :Price :Date :Notes :Type :Brokerage) - clojure.lang.PersistentHashMap : nil ATT
Key :Stock Value ATT
Key :AccountId Value 1
Key :TradeId Value 37
...
The issue is (:TradeId record)
doesn't work even though it exists as a key. Iterating through all keys and values - Line 3 - yields the right value.
Tried renaming the column in the csv but no change in behavior. I see no difference from the other columns (which work) except that this is the first column in the csv.
The hashmap is created from code like this - reading records from a CSV. Standard code from the clojure.data.csv package.
(->> (csv/read-csv reader)
csv-data->maps
(map #(my-function some-args %))
doall))
(defn csv-data->maps
"Return the csv records as a vector of maps"
[csv-data]
(map zipmap
(->> (first csv-data) ;; First row is the header
(map keyword) ;; Drop if you want string keys instead
repeat)
(rest csv-data)))
Upvotes: 2
Views: 149
Reputation: 10865
The "first column" thing is definitely suspicous and points to some invisible characters such as a BOM quietly attaching itself to your first keyword.
To debug try printing out the hex of the names of the keywords. And/or maybe you'll see something if you do a hex dump, e.g., with head -n 2 file.csv | od -x
, of the first few lines of the input file.
Upvotes: 2
Reputation: 136613
Once I reached the point of trying anything, I copied the keyword from the REPL and pasted it into VSCode and sure enough - there was this weird looking character :?Id
within the keyword. Using the weird keyword, the lookup worked.
Workaround: Added a dummy column as the first column.
Then things started to click into place, I remembered reading something on BOM in the csv reader project docs. https://github.com/clojure/data.csv#byte-order-mark
Downloaded a hexdump file viewer which confirmed the problem bytes at the start of the file.
o;?Id,AccountId,...
Final solution: Before passing the reader to the data.csv read function, skip over the unwanted bytes.
(.skip reader 1)
The world makes sense again.
Upvotes: 1
Reputation: 91907
I would try two things. First, print the type of each key. They should all be clojure.lang.Keyword, if the creation code you included is accurate and my-function
preserves their type; but if you created it in some other way and misremembered, you might discover that the key is a symbol, or a string or something like that. In general, don't use println
on anything but strings, because it's pretty low-fidelity. prn
is better at conveying an accurate picture of your data - it's not perfect, but at least you can tell a string from a keyword with it.
Second, look at the printed values more carefully, e.g. with od -t x1
- or you could do it in process with something like:
(let [k (key (first m)), s (name k)]
(clojure.string/join " "
(for [c s]
(format "%02x" (int c)))))
If the result isn't "53 74 6f 63 6b"
, then you have some weird characters in your file - maybe nonprinting characters, maybe something that looks like a capital S but isn't, whatever.
Upvotes: 1