【发布时间】:2012-01-07 11:07:03
【问题描述】:
我正在尝试将从映射操作返回的(惰性)序列传递给另一个映射操作,以便我可以查找第一个序列中的元素。该代码正在从文本文件(行/列格式)中解析一些足球赛程,对其进行清理,然后返回地图。
代码如下:
(ns fixtures.test.lazytest
(:require [clojure.string :as str])
(:use [clojure.test]))
(defn- column-map
"Produce map with column labels given raw data, return nil if not enough columns"
[cols]
(let [trimmed-cols (map str/trim cols)
column-names {0 :fixture-type, 1 :division, 2 :home-team, 4 :away-team}]
(if (> (count cols) (apply max (keys column-names)))
(zipmap (vals column-names) (map trimmed-cols (keys column-names)))
nil)))
(deftest test-mapping
(let [cols '["L" " Premier " " Chelsea " "v" "\tArsenal "]
fixture (column-map cols)]
(is (= "Arsenal" (fixture :away-team)))
(is (= "Chelsea" (fixture :home-team)))
(is (= "Premier" (fixture :division)))
(is (= "L" (fixture :fixture-type)))
)
)
(run-tests 'fixtures.test.lazytest)
我采取的方法是:
- 清理列数据的向量(删除前导/尾随空格)
- 使用 zipmap,将列名关键字与其对应的列数据中的元素组合起来(注意,并非所有列都被使用)
问题是,在zipmap中使用trimmed-cols会导致
java.lang.ClassCastException: clojure.lang.LazySeq 无法转换为 clojure.lang.IFn
我想我知道为什么会这样......因为 trimmed-cols 是一个 LazySeq,所以从 zipmap 调用的映射反对接收非函数作为其第一个参数。
要解决这个问题,我可以将 let 更改为:
trimmed-cols (vec (map str/trim cols))
但这感觉不是“最佳”选项。
所以:
- 是否有一个很好的通用解决方案可以将映射操作的结果用作另一个映射的“函数”参数?
- 是否有更好的方法可以从原始值数据向量导出 {:value} 对的映射,其中未使用所有向量元素?
(我犹豫是否要惯用解决方案,但想象一下,一定有一种普遍接受的方式来做到这一点。)
【问题讨论】: