Clojure - 如何对每列应用不同的功能?

时间:2014-07-04 18:33:29

标签: csv vector map clojure

我是Clojure的新手,为了好玩而玩它。

我正在阅读CSV文件,并希望对每列应用不同的功能。什么是优雅(简洁和可读)的方式来做到这一点? 我探讨了两种方法:

  • 处理行向量:
每行

......

(def row-1 ["John", "24"])

...我想对每个元素应用不同的函数,并获得此结果:

["John", 24]

我想要使用的功能是:

(def converters-1 [identity, read-string])

是否有一种简单的方法可以将converters-1函数应用于row-1元素?


  • 在地图上工作:

使用这种方法,我首先将每一行转换为地图:

(def row-2 {:name "John", :age "24"})

编辑:我想获得这张地图:

{:name "John", :age 24}

转换器也存储在地图中:

(def converters-2 {:name identity, :age read-string})

是否有一种简单的方法可以将正确的转换器应用于row-2元素?


我将有兴趣阅读这两种方法的解决方案。

最后,我将数据放入地图中。我不确定在获取此地图之前或之后是否要进行转换。

3 个答案:

答案 0 :(得分:4)

使用map作为序列;使用merge-with表示地图。

user=> (map #(% %2) converters-1 row-1)
("John" 24)
user=> (merge-with #(% %2) converters-2 row-2)
{:name "John", :age 24}

答案 1 :(得分:1)

(map #(%1 %2) converters-1 row-1)
;; ("John" 24)

if (def row-2 {:name "John", :age "24"})(在你的例子中它是一个整数)

(for [x (keys converters-2)] ((converters-2 x) (row-2 x)))
;; ("John" 24)

答案 2 :(得分:0)

我找到了地图方法的解决方案,但它不如迭戈的矢量解决方案那么优雅。

(into {} (map (fn [[k v]] 
    [k  ((converters-2 k) v)]
) row-2))

这种地图方法有更简单的解决方案吗? 我错过了一个可以简化它的核心功能吗?

编辑:阅读迭戈的编辑,我也可以使用keys

(into {} (map #( 
    [%  ((converters-2 %) (row-2 %))]   ; the key, and the converted value
) (keys row-2)))

但是我更喜欢之前的解决方案,因为它不需要评论:显而易见的是密钥和值的变化。另外,在此解决方案中,我只需要编写row-2一次。

编辑2:如果我写(converters-2 k identity),那么我只需要指出需要转换的列。对于其他列(例如此处:name),identity是默认转换器。与矢量方法相比,这是一个优势。

编辑3:我使用update-in找到了另一种地图方法解决方案:

(reduce #(update-in %1 [%2] (converters-2 %2)) row-2 (keys row-2))

嗯,既然已经写好了,对我的新手来说,阅读和理解起来比较困难。

到目前为止,矢量解决方案仍然是最好的。我会睁大眼睛寻找更好的地图解决方案;它可能会在某一天派上用场。