Idiomatic sequence slice in Clojure
在Python中,有一种方便的方法可以获取称为"切片"的列表:
1 2 3 4 5 6 7 | a = [1,2,3,4,5,6,7,8,9,10] # ≡ a = range(1,10) a[:3] # get first 3 elements a[3:] # get all elements except the first 3 a[:-3] # get all elements except the last 3 a[-3:] # get last 3 elements a[3:7] # get 4 elements starting from 3rd (≡ from 3rd to 7th exclusive) a[3:-3] # get all elements except the first 3 and the last 3 |
在Clojure中玩
1 2 3 4 5 6 7 | (def a (take 10 (iterate inc 1))) (take 3 a) (drop 3 a) (take (- (count a) 3) a) (drop (- (count a) 3) a) (drop 3 (take 7 a)) (drop 3 (take (- (count a) 3) a)) |
我的问题是:如何在Clojure中切片序列? 换句话说,返回序列不同部分的正确方法是什么?
您可以使用
1 2 3 4 5 6 7 | (def a (take 10 (iterate inc 1))) (take 3 a) ; get first 3 elements (drop 3 a) ; get all elements except the first 3 (drop-last 3 a) ; get all elements except the last 3 (take-last 3 a) ; get last 3 elements (drop 3 (take 7 a)) ; get 4 elements starting from 3 (drop 3 (drop-last 3 a)) ; get all elements except the first and the last 3 |
并且如下面的注释中所建议,您可以使用
1 2 | (->> a (take 7) (drop 3)) ; get 4 elements starting from 3 (->> a (drop-last 3) (drop 3)) ; get all elements except the first and the last 3 |
我认为如果仅对列表应用两个操作,则这两种方法都非常易读,但是当您有一个长字符串,如
Python的序列概念与Clojure的概念非常不同。
在Python中,
-
序列是由索引的有限有序集
非负数;和 -
列表是可变序列,您可以在其中添加切片或删除切片
切片。
在Clojure中
-
序列是支持
first ,rest 和
cons ; -
列表是具有
cons 的不可变顺序集合(或
rest )添加(或删除)first 元素(因此返回列表
修改)。
Clojure中最接近Python列表的是向量。正如Adam Sznajder所建议的那样,尽管不能像在Python中那样添加或删除切片,但可以使用
你的例子变成...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | (def a (vec (range 1 (inc 10)))) (subvec a 0 3) ; [1 2 3] (subvec a 3) ; [4 5 6 7 8 9 10] (subvec a 0 (- (count a) 3)) ; [1 2 3 4 5 6 7] (subvec a (- (count a) 3)) ; [8 9 10] (subvec a 3 (+ 3 4)) ; [4 5 6 7] (subvec a 3 (- (count a) 3)) ; [4 5 6 7] |
有一个功能
http://clojuredocs.org/clojure_core/clojure.core/subvec
切片序列有点"代码异味"-序列通常设计用于顺序访问项目。
如果您要进行大量切片/串联,则可以使用更好的数据结构,尤其是检出RRB-Tree矢量实现:
- https://github.com/clojure/core.rrb-vector
这支持非常有效的