为什么这个关键字函数查找在哈希图中不起作用?
Why doesn't this keyword function lookup work in a hashmap?
我想我需要一些眼球才能对此有所了解
(println record)
(println (keys record) " - " (class record) " : " (:TradeId record) (:Stock record))
(doall (map #(println "Key " % "Value " (% record)) (keys record)))
输出:
{: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
...
问题是 (:TradeId record)
即使它作为密钥存在也不起作用。遍历所有键和值 - 第 3 行 - 产生正确的值。
尝试重命名 csv 中的列,但行为没有变化。除了这是 csv 中的第一列之外,我看不出与其他列(哪些有效)有什么不同。
哈希图是从这样的代码创建的——从 CSV 中读取记录。 clojure.data.csv 包中的标准代码。
(->> (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)))
我会尝试两件事。首先,打印每个键的类型。它们应该都是 clojure.lang.Keyword,如果您包含的创建代码是准确的并且 my-function
保留了它们的类型;但是如果您以其他方式创建它并且记错了,您可能会发现该键是一个符号,或者一个字符串或类似的东西。一般来说,不要在字符串以外的任何东西上使用 println
,因为它的保真度很低。 prn
可以更好地传达您的数据的准确图片 - 它并不完美,但至少您可以使用它从关键字中分辨出字符串。
其次,更仔细地查看打印值,例如使用 od -t x1
- 或者你可以在过程中使用类似的东西来完成它:
(let [k (key (first m)), s (name k)]
(clojure.string/join " "
(for [c s]
(format "%02x" (int c)))))
如果结果不是 "53 74 6f 63 6b"
,那么您的文件中有一些奇怪的字符 - 可能是非打印字符,可能是一些看起来像大写字母 S 但实际上不是的字符。
一旦我到了尝试任何东西的地步,我就从 REPL 中复制关键字并将其粘贴到 VSCode 中,果然 - 关键字中有这个看起来很奇怪的字符 :?Id
。使用 weird 关键字,查找有效。
解决方法:添加一个虚拟列作为第一列。
然后事情开始顺利,我记得在 csv reader 项目文档中读过一些关于 BOM 的内容。 https://github.com/clojure/data.csv#byte-order-mark
下载了一个 hexdump 文件查看器,它确认了文件开头的问题字节。
o;?Id,AccountId,...
最终解决方案:在将 reader 传递给 data.csv 读取函数之前,跳过不需要的字节。
(.skip reader 1)
世界又变得有意义了。
“第一列”绝对可疑,它指向一些不可见的字符,例如 BOM 悄悄地附加到您的第一个关键字。
要调试,请尝试打印出关键字名称的十六进制。 And/or 如果您对输入文件的前几行进行十六进制转储,例如使用 head -n 2 file.csv | od -x
,也许您会看到一些东西。
我想我需要一些眼球才能对此有所了解
(println record)
(println (keys record) " - " (class record) " : " (:TradeId record) (:Stock record))
(doall (map #(println "Key " % "Value " (% record)) (keys record)))
输出:
{: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
...
问题是 (:TradeId record)
即使它作为密钥存在也不起作用。遍历所有键和值 - 第 3 行 - 产生正确的值。
尝试重命名 csv 中的列,但行为没有变化。除了这是 csv 中的第一列之外,我看不出与其他列(哪些有效)有什么不同。
哈希图是从这样的代码创建的——从 CSV 中读取记录。 clojure.data.csv 包中的标准代码。
(->> (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)))
我会尝试两件事。首先,打印每个键的类型。它们应该都是 clojure.lang.Keyword,如果您包含的创建代码是准确的并且 my-function
保留了它们的类型;但是如果您以其他方式创建它并且记错了,您可能会发现该键是一个符号,或者一个字符串或类似的东西。一般来说,不要在字符串以外的任何东西上使用 println
,因为它的保真度很低。 prn
可以更好地传达您的数据的准确图片 - 它并不完美,但至少您可以使用它从关键字中分辨出字符串。
其次,更仔细地查看打印值,例如使用 od -t x1
- 或者你可以在过程中使用类似的东西来完成它:
(let [k (key (first m)), s (name k)]
(clojure.string/join " "
(for [c s]
(format "%02x" (int c)))))
如果结果不是 "53 74 6f 63 6b"
,那么您的文件中有一些奇怪的字符 - 可能是非打印字符,可能是一些看起来像大写字母 S 但实际上不是的字符。
一旦我到了尝试任何东西的地步,我就从 REPL 中复制关键字并将其粘贴到 VSCode 中,果然 - 关键字中有这个看起来很奇怪的字符 :?Id
。使用 weird 关键字,查找有效。
解决方法:添加一个虚拟列作为第一列。
然后事情开始顺利,我记得在 csv reader 项目文档中读过一些关于 BOM 的内容。 https://github.com/clojure/data.csv#byte-order-mark
下载了一个 hexdump 文件查看器,它确认了文件开头的问题字节。
o;?Id,AccountId,...
最终解决方案:在将 reader 传递给 data.csv 读取函数之前,跳过不需要的字节。
(.skip reader 1)
世界又变得有意义了。
“第一列”绝对可疑,它指向一些不可见的字符,例如 BOM 悄悄地附加到您的第一个关键字。
要调试,请尝试打印出关键字名称的十六进制。 And/or 如果您对输入文件的前几行进行十六进制转储,例如使用 head -n 2 file.csv | od -x
,也许您会看到一些东西。