[英]What's the best way to handle this sequence transformation in Clojure?
I'm new to Clojure, and I've been translating some data manipulation work I did recently as an aid to learning. 我是Clojure的新手,我一直在翻译我最近做的一些数据处理工作,以帮助学习。 I've got a function translation that works fine, and is shorter, but feels much less readable.
我有一个功能翻译,工作正常,而且更短,但感觉更不易读。 Can anyone suggest a more readable and/or more idiomatic way to handle this?
任何人都可以建议更可读和/或更惯用的方式来处理这个问题吗?
In Python: 在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
My attempt at a Clojure translation: 我尝试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))))))
It could be that it's less readable just because of my inexperience with Clojure, but in particular, the trick of prepending an element to the input vector feels to me like it obscures the intention. 可能因为我对Clojure缺乏经验而不太可读,但特别是,将元素添加到输入向量的技巧让我觉得它模糊了意图。 All the solutions I tried which didn't use the prepending trick were much longer and uglier.
我试过的所有没有使用前置技巧的解决方案都要长得多,而且更加丑陋。
Many sequence transformations are incredibly elegant in Clojure, but the ones that I find challenging so far are ones like this one, which a) lend themselves to manipulation by index rather than by element, and/or b) require special handling for certain elements. 在Clojure中,许多序列转换非常优雅,但到目前为止我发现的那些是像这样的,a)适合于通过索引而不是元素进行操作,和/或b)需要对某些元素进行特殊处理。
Thanks for any suggestions. 谢谢你的任何建议。
Idiomatic Clojure tends to manipulate the sequences as a whole, rather than individual elements. 惯用语Clojure倾向于整体操纵序列,而不是单个元素。 You could define
create-diff-vector
in English as: 你可以用英语定义
create-diff-vector
:
The result is a vector consisting of: 结果是一个由以下内容组成的向量:
start-zero
is true or false, respectively; start-zero
是true还是false; followed by The second part can be illustrated thusly: for the input (31 41 59 26 53)
, we have 第二部分可以这样说明:对于输入
(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)
Which, translated to Clojure, becomes remarkably concise: 其中,翻译成Clojure,变得非常简洁:
(defn diff-vector [v start-zero?]
(into [(if start-zero? 0 (first v))]
(map - (rest v) v))))
A few points to note: 需要注意的几点:
start-zero?
start-zero?
结束start-zero?
serves as a hint that a boolean is expected here. map
ping a function over sequences of different lengths terminates upon the end of the shortest sequence. map
函数终止于最短序列的末尾。 This implementation would be more idiomatic: 这种实现更加惯用:
(defn create-diff-vector [v start-with-zero?]
(let [v (cons (if start-with-zero? (first v) 0) v)]
(map - (rest v) v)))
I first prepend either the first value of the vector or 0 to the input vector. 我首先将向量的第一个值或0添加到输入向量。 Then I use
map
to subtract the vector from itself, shifted by one position. 然后我使用
map
从自身中减去向量,移动一个位置。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.