目前我的功能如下:
(def csv-file (.getFile (clojure.java.io/resource "datasources.csv")))
(defn process-csv [file]
(with-open [in-file (io/reader file)]
(doall (csv/read-csv in-file))))
我现在需要做的是根据csv中的/ group by列生成向量,即我的process-csv
输出如下所示:
(["atom" "neutron" "photon"]
[10 22 3]
[23 23 67])
我的目标是从列原子,中子和放大器生成3个向量。光子:
atom: [10 23]
neutron: [22 23]
photon: [3 67]
仅供参考,我在读取csv文件之前定义了3个空向量:
(def atom [])
(def neutron[])
(def photon[])
答案 0 :(得分:6)
首先你不能修改这些向量,你已经定义了。这是不可变数据结构的本质。如果您确实需要可变向量,请使用user> (def items (rest '(["atom" "neutron" "photon"]
[10 22 3]
[23 23 67]
[1 2 3]
[5 6 7])))
user> (let [[atom neutron photon] (apply map vector items)]
{:atom atom :neutron neutron :photon photon})
{:atom [10 23 1 5], :neutron [22 23 2 6], :photon [3 67 3 7]}
。
你可以这样解决你的任务:
(apply map vector items)
它是如何工作的:
(map vector [10 22 3] [23 23 67] [1 2 3] [5 6 7])
等于以下内容:
user> (def items '(["atom" "neutron" "photon"]
[10 22 3]
[23 23 67]
[1 2 3]
[5 6 7]))
#'user/items
user> (zipmap (map keyword (first items))
(apply map vector (rest items)))
{:atom [10 23 1 5], :neutron [22 23 2 6], :photon [3 67 3 7]}
它会获取每个coll的第一项并制作它们的矢量,然后是第二项,依此类推。
另外,通过从csv数据头中精确获取行列名,可以使其更加健壮:
grep -l
答案 1 :(得分:1)
我将说明您可以使用的其他一些方法,这些方法可以与leetwinski说明的方法结合使用。像leetwinski一样,我建议使用哈希映射作为最终结构,而不是使用包含向量的三个符号。这取决于你。
如果您愿意,可以使用core.matrix的transpose
来执行leetwinski对(apply map vector ...)
所做的事情:
(require '[clojure.core.matrix :as mx])
(mx/transpose '(["atom" "neutron" "photon"] [10 22 3] [23 23 67]))
产生:
[["atom" 10 23] ["neutron" 22 23] ["photon" 3 67]]
transpose
旨在用于实现core.matrix协议的任何类型的矩阵,并且正常的Clojure序列序列被core.matrix视为矩阵。
要生成地图,这里有一种方法:
(into {} (map #(vector (keyword (first %)) (rest %))
(mx/transpose '(["atom" "neutron" "photon"] [10 22 3] [23 23 67]))))
产生:
{:atom (10 23), :neutron (22 23), :photon (3 67)}
keyword
将字符串变为关键字。 #(vector ...)
成对,(into {} ...)
获取对的序列并从中生成哈希映射。
或者,如果您想要变量在vars中,如您所指定的那样,那么您可以使用leetwinski的let
方法的变体。我建议不要def
使用符号atom
,因为这是Clojure中标准函数的名称。
(let [[adam neutron proton] (mx/transpose
(rest '(["atom" "neutron" "photon"]
[10 22 3]
[23 23 67])))]
(def adam adam)
(def neutron neutron)
(def proton proton))
在def
中使用let
并不是一个好方法,但你可以做到。另外,我不建议将let
定义的局部变量命名为与顶级变量相同的名称。如您所见,如果使def
混乱。我故意这样做是为了展示范围规则的工作原理:在(def adam adam)
中,“adam”的第一个实例代表定义的顶级变量,而“adam”的第二个实例代表本地由let
定义的var,包含[10 23]
。结果是:
adam ;=> [10 23]
neutron ;=> [22 23]
proton ;=> [3 67]
(我认为可能有一些细微之处,我表达的错误。如果是这样,有人无疑会对此发表评论。)