我是Clojure的新手,我一直在翻译我最近做的一些数据处理工作,以帮助学习。我有一个功能翻译,工作正常,而且更短,但感觉更不易读。任何人都可以建议一种更具可读性和/或更具惯用性的方法来处理这个问题吗?
在Python中:
def createDifferenceVector(v,startWithZero=True):
deltas = []
for i in range(len(v)):
if i == 0:
if startWithZero:
deltas.append(0.0)
else:
deltas.append(v[0])
else:
deltas.append(v[i] - v[i-1])
return deltas
我尝试翻译Clojure:
(defn create-diff-vector [v start-zero]
(let [ext-v (if start-zero
(cons (first v) v)
(cons 0 v))]
(for [i (range 1 (count ext-v))]
(- (nth ext-v i) (nth ext-v (- i 1))))))
可能因为我对Clojure缺乏经验而不太可读,但特别是,将元素添加到输入向量的技巧让我觉得它模糊了意图。我试过的所有没有使用前置技巧的解决方案都要长得多,而且更加丑陋。
许多序列转换在Clojure中非常优雅,但到目前为止我发现的那些是像这样的,a)适合于通过索引而不是元素进行操作,和/或b)需要特殊处理某些元素。
感谢您的任何建议。
答案 0 :(得分:12)
惯用语Clojure倾向于操纵序列作为一个整体,而不是单个元素。您可以将英语中的create-diff-vector
定义为:
结果是一个包含以下内容的向量:
start-zero
是真还是假; 第二部分可以这样说明:对于输入(31 41 59 26 53)
,我们有
input without the first element: (41 59 26 53) - input without the last element: (31 41 59 26) =================================================== result: (10 18 -33 27)
翻译成Clojure,变得非常简洁:
(defn diff-vector [v start-zero?]
(into [(if start-zero? 0 (first v))]
(map - (rest v) v))))
需要注意几点:
start-zero?
末尾的问号表示此处需要布尔值。map
对不同长度的序列执行ping函数的事实在最短序列结束时终止。答案 1 :(得分:1)
这种实现更加惯用:
(defn create-diff-vector [v start-with-zero?]
(let [v (cons (if start-with-zero? (first v) 0) v)]
(map - (rest v) v)))
我首先将向量的第一个值或0添加到输入向量。然后我使用map
从自身中减去矢量,移动一个位置。