[ACCEPTED]-Idiomatic sequence slice in Clojure-slice
You can simplify all the ones using count
by 10 using take-last
or drop-last
instead:
(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
And as suggested in the 9 comments below, you can use the ->>
macro to 8 "thread" several operation together. For 7 example, the last two lines could also be 6 written like this:
(->> 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
I think the two methods 5 are both very readable if you are only applying 4 two operations to a list, but when you have 3 a long string like take
, map
, filter
, drop
, first
then using the 2 ->>
macro can make the code much easier to 1 read and probably even easier for to write.
Python's notion of a sequence is very different 10 from Clojure's.
In Python,
- a sequence is a finite ordered set indexed by non-negative numbers; and
- a list is a mutable sequence which you can add slices to or remove slices from.
In Clojure,
- a sequence is an interface supporting
first
,rest
, andcons
; - a list is an immutable sequential collection with
cons
(orrest
) adding (or removing)first
elements (returning lists so modified, anyway).
The 9 nearest thing in Clojure to a Python list 8 is a vector. As Adam Sznajder suggests, you can slice it using subvec
, though 7 you can't add or remove slices as you can 6 in Python.
subvec
is a fast constant-time operation, whereas 5 drop
makes you pay for the number of elements 4 bypassed (take
makes you pay for the elements 3 you traverse, but these are the ones you 2 are interested in).
Your examples become 1 ...
(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]
There is a function subvec
. Unfortunately, it 2 only works with vectors so you would have 1 to transform your sequence:
Slicing a sequence is a bit of a "code 7 smell" - a sequence in general is designed 6 for sequential access of items.
If you are 5 going to do a lot of slicing / concatenation, there 4 are much better data structures available, in 3 particular checkout the RRB-Tree vector 2 implementation:
This supports very efficient 1 subvec
and catvec
operations.
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.