diff --git a/README.md b/README.md index 34443e2..ac54f94 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Include this in your emacs settings to get syntax highlighting: * [-flatten-n](#-flatten-n-num-list) `(num list)` * [-concat](#-concat-rest-lists) `(&rest lists)` * [-mapcat](#-mapcat-fn-list) `(fn list)` -* [-slice](#-slice-list-from-optional-to) `(list from &optional to)` +* [-slice](#-slice-list-from-optional-to-step) `(list from &optional to step)` * [-take](#-take-n-list) `(n list)` * [-drop](#-drop-n-list) `(n list)` * [-take-while](#-take-while-pred-list) `(pred list)` @@ -335,15 +335,20 @@ Thus function `fn` should return a list. (--mapcat (list 0 it) '(1 2 3)) ;; => '(0 1 0 2 0 3) ``` -#### -slice `(list from &optional to)` +#### -slice `(list from &optional to step)` Return copy of `list`, starting from index `from` to index `to`. -`from` or `to` may be negative. + +`from` or `to` may be negative. These values are then interpreted +modulo the length of the list. + +If `step` is a number, only each STEPth item in the resulting +section is returned. Defaults to 1. ```cl (-slice '(1 2 3 4 5) 1) ;; => '(2 3 4 5) (-slice '(1 2 3 4 5) 0 3) ;; => '(1 2 3) -(-slice '(1 2 3 4 5) 1 -1) ;; => '(2 3 4) +(-slice '(1 2 3 4 5 6 7 8 9) 1 -1 2) ;; => '(2 4 6 8) ``` #### -take `(n list)` diff --git a/dash.el b/dash.el index 7c1a772..240b93d 100644 --- a/dash.el +++ b/dash.el @@ -432,13 +432,19 @@ Returns `nil` both if all items match the predicate, and if none of the items ma (defalias '-only-some-p '-only-some?) (defalias '--only-some-p '--only-some?) -(defun -slice (list from &optional to) +(defun -slice (list from &optional to step) "Return copy of LIST, starting from index FROM to index TO. -FROM or TO may be negative." + +FROM or TO may be negative. These values are then interpreted +modulo the length of the list. + +If STEP is a number, only each STEPth item in the resulting +section is returned. Defaults to 1." (let ((length (length list)) (new-list nil)) ;; to defaults to the end of the list (setq to (or to length)) + (setq step (or step 1)) ;; handle negative indices (when (< from 0) (setq from (mod from length))) @@ -447,7 +453,8 @@ FROM or TO may be negative." ;; iterate through the list, keeping the elements we want (--each-while list (< it-index to) - (when (>= it-index from) + (when (and (>= it-index from) + (= (mod (- from it-index) step) 0)) (push it new-list))) (nreverse new-list))) diff --git a/dev/examples.el b/dev/examples.el index 28fceb6..aabd343 100644 --- a/dev/examples.el +++ b/dev/examples.el @@ -70,10 +70,19 @@ (defexamples -slice (-slice '(1 2 3 4 5) 1) => '(2 3 4 5) (-slice '(1 2 3 4 5) 0 3) => '(1 2 3) - (-slice '(1 2 3 4 5) 1 -1) => '(2 3 4) + (-slice '(1 2 3 4 5 6 7 8 9) 1 -1 2) => '(2 4 6 8) (-slice '(1 2 3 4 5) 0 10) => '(1 2 3 4 5) ;; "to > length" should not fill in nils! (-slice '(1 2 3 4 5) -3) => '(3 4 5) - (-slice '(1 2 3 4 5) -3 -1) => '(3 4)) + (-slice '(1 2 3 4 5) -3 -1) => '(3 4) + (-slice '(1 2 3 4 5 6) 0 nil 1) => '(1 2 3 4 5 6) + (-slice '(1 2 3 4 5 6) 0 nil 2) => '(1 3 5) + (-slice '(1 2 3 4 5 6) 0 nil 3) => '(1 4) + (-slice '(1 2 3 4 5 6) 0 nil 10) => '(1) + (-slice '(1 2 3 4 5 6) 1 4 2) => '(2 4) + (-slice '(1 2 3 4 5 6) 2 6 3) => '(3 6) + (-slice '(1 2 3 4 5 6) 2 -1 2) => '(3 5) + (-slice '(1 2 3 4 5 6) -4 -1 2) => '(3 5) + (-slice '(1 2 3 4 5 6) 1 2 10) => '(2)) (defexamples -take (-take 3 '(1 2 3 4 5)) => '(1 2 3)