Add indexing operations

master
Matus Goljer 13 years ago
parent dbcb3ef2e7
commit 87c8b91e1b
  1. 92
      README.md
  2. 68
      dash.el
  3. 34
      dev/examples.el

@ -101,6 +101,16 @@ To get function combinators:
* [-partition-by-header](#-partition-by-header-fn-list) `(fn list)`
* [-group-by](#-group-by-fn-list) `(fn list)`
### Indexing
* [-elem-index](#-elem-index-elem-list) `(elem list)`
* [-elem-indices](#-elem-indices-elem-list) `(elem list)`
* [-find-index](#-find-index-pred-list) `(pred list)`
* [-find-indices](#-find-indices-pred-list) `(pred list)`
* [-select-by-indices](#-select-by-indices-indices-list) `(indices list)`
* [-grade-up](#-grade-up-comparator-list) `(comparator list)`
* [-grade-down](#-grade-down-comparator-list) `(comparator list)`
### Set operations
* [-union](#-union-list-list2) `(list list2)`
@ -678,6 +688,88 @@ elements of `list`. Keys are compared by `equal`.
```
## Indexing
#### -elem-index `(elem list)`
Return the index of the first element in the given `list` which
is equal to the query element `elem`, or nil if there is no
such element.
```cl
(-elem-index 2 '(6 7 8 2 3 4)) ;; => 3
(-elem-index "bar" '("foo" "bar" "baz")) ;; => 1
(-elem-index '(1 2) '((3) (5 6) (1 2) nil)) ;; => 2
```
#### -elem-indices `(elem list)`
Return the indices of all elements in `list` equal to the query
element `elem`, in ascending order.
```cl
(-elem-indices 2 '(6 7 8 2 3 4 2 1)) ;; => '(3 6)
(-elem-indices "bar" '("foo" "bar" "baz")) ;; => '(1)
(-elem-indices '(1 2) '((3) (1 2) (5 6) (1 2) nil)) ;; => '(1 3)
```
#### -find-index `(pred list)`
Return the indices of all elements in `list` satisfying the
predicate `pred`, in ascending order.
```cl
(-find-index 'even? '(2 4 1 6 3 3 5 8)) ;; => 0
(--find-index (< 5 it) '(2 4 1 6 3 3 5 8)) ;; => 3
(-find-index (-partial 'string-lessp "baz") '("bar" "foo" "baz")) ;; => 1
```
#### -find-indices `(pred list)`
Take a predicate `pred` and a `list` and return the index of the
first element in the list satisfying the predicate, or nil if
there is no such element.
```cl
(-find-indices 'even? '(2 4 1 6 3 3 5 8)) ;; => '(0 1 3 7)
(--find-indices (< 5 it) '(2 4 1 6 3 3 5 8)) ;; => '(3 7)
(-find-indices (-partial 'string-lessp "baz") '("bar" "foo" "baz")) ;; => '(1)
```
#### -select-by-indices `(indices list)`
Return a list whose elements are elements from `list` selected
as `(nth i list)` for all i from `indices`.
```cl
(-select-by-indices '(4 10 2 3 6) '("v" "e" "l" "o" "c" "i" "r" "a" "p" "t" "o" "r")) ;; => '("c" "o" "l" "o" "r")
(-select-by-indices '(2 1 0) '("a" "b" "c")) ;; => '("c" "b" "a")
(-select-by-indices '(0 1 2 0 1 3 3 1) '("f" "a" "r" "l")) ;; => '("f" "a" "r" "f" "a" "l" "l" "a")
```
#### -grade-up `(comparator list)`
Grades elements of `list` using `comparator` relation, yielding a
permutation vector such that applying this permutation to `list`
sorts it in ascending order.
```cl
(-grade-up '< '(3 1 4 2 1 3 3)) ;; => '(1 4 3 0 5 6 2)
(let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-up '< l) l)) ;; => '(1 1 2 3 3 3 4)
```
#### -grade-down `(comparator list)`
Grades elements of `list` using `comparator` relation, yielding a
permutation vector such that applying this permutation to `list`
sorts it in descending order.
```cl
(-grade-down '< '(3 1 4 2 1 3 3)) ;; => '(2 0 5 6 3 1 4)
(let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-down '< l) l)) ;; => '(4 3 3 3 2 1 1)
```
## Set operations
#### -union `(list list2)`

@ -697,6 +697,65 @@ When called, the returned function calls FN with ARGS first and
then additional args."
(apply 'apply-partially fn args))
(defun -elem-index (elem list)
"Return the index of the first element in the given LIST which
is equal to the query element ELEM, or nil if there is no
such element."
(car (-elem-indices elem list)))
(defun -elem-indices (elem list)
"Return the indices of all elements in LIST equal to the query
element ELEM, in ascending order."
(-find-indices (-partial 'equal elem) list))
(defun -find-indices (pred list)
"Take a predicate PRED and a LIST and return the index of the
first element in the list satisfying the predicate, or nil if
there is no such element."
(let ((i 0))
(apply 'append (--map-indexed (when (funcall pred it) (list it-index)) list))))
(defmacro --find-indices (form list)
"Anaphoric version of `-find-indices'."
`(-find-indices (lambda (it) ,form) ,list))
(defun -find-index (pred list)
"Return the indices of all elements in LIST satisfying the
predicate PRED, in ascending order."
(car (-find-indices pred list)))
(defmacro --find-index (form list)
"Anaphoric version of `-find-index'."
`(-find-index (lambda (it) ,form) ,list))
(defun -select-by-indices (indices list)
"Return a list whose elements are elements from LIST selected
as `(nth i list)` for all i from INDICES."
(let (r)
(--each indices
(!cons (nth it list) r))
(nreverse r)))
(defun -grade-up (comparator list)
"Grades elements of LIST using COMPARATOR relation, yielding a
permutation vector such that applying this permutation to LIST
sorts it in ascending order."
;; ugly hack to "fix" lack of lexical scope
(let ((comp `(lambda (it other) (funcall ',comparator (car it) (car other)))))
(->> (--map-indexed (cons it it-index) list)
(-sort comp)
(-map 'cdr))))
(defun -grade-down (comparator list)
"Grades elements of LIST using COMPARATOR relation, yielding a
permutation vector such that applying this permutation to LIST
sorts it in descending order."
;; ugly hack to "fix" lack of lexical scope
(let ((comp `(lambda (it other) (funcall ',comparator (car other) (car it)))))
(->> (--map-indexed (cons it it-index) list)
(-sort comp)
(-map 'cdr))))
(defmacro -> (x &optional form &rest more)
"Threads the expr through the forms. Inserts X as the second
item in the first form, making a list of it if it is not a list
@ -1010,6 +1069,15 @@ The items for the comparator form are exposed as \"it\" and \"other\"."
"-cut"
"-orfn"
"-andfn"
"-elem-index"
"-elem-indices"
"-find-indices"
"--find-indices"
"-find-index"
"--find-index"
"-select-by-indices"
"-grade-up"
"-grade-down"
"->"
"->>"
"-->"

@ -238,6 +238,40 @@
(-group-by 'even? '(1 1 2 2 2 3 4 6 8)) => '((nil . (1 1 3)) (t . (2 2 2 4 6 8)))
(--group-by (car (split-string it "/")) '("a/b" "c/d" "a/e")) => '(("a" . ("a/b" "a/e")) ("c" . ("c/d")))))
(def-example-group "Indexing" nil
(defexamples -elem-index
(-elem-index 2 '(6 7 8 2 3 4)) => 3
(-elem-index "bar" '("foo" "bar" "baz")) => 1
(-elem-index '(1 2) '((3) (5 6) (1 2) nil)) => 2)
(defexamples -elem-indices
(-elem-indices 2 '(6 7 8 2 3 4 2 1)) => '(3 6)
(-elem-indices "bar" '("foo" "bar" "baz")) => '(1)
(-elem-indices '(1 2) '((3) (1 2) (5 6) (1 2) nil)) => '(1 3))
(defexamples -find-index
(-find-index 'even? '(2 4 1 6 3 3 5 8)) => 0
(--find-index (< 5 it) '(2 4 1 6 3 3 5 8)) => 3
(-find-index (-partial 'string-lessp "baz") '("bar" "foo" "baz")) => 1)
(defexamples -find-indices
(-find-indices 'even? '(2 4 1 6 3 3 5 8)) => '(0 1 3 7)
(--find-indices (< 5 it) '(2 4 1 6 3 3 5 8)) => '(3 7)
(-find-indices (-partial 'string-lessp "baz") '("bar" "foo" "baz")) => '(1))
(defexamples -select-by-indices
(-select-by-indices '(4 10 2 3 6) '("v" "e" "l" "o" "c" "i" "r" "a" "p" "t" "o" "r")) => '("c" "o" "l" "o" "r")
(-select-by-indices '(2 1 0) '("a" "b" "c")) => '("c" "b" "a")
(-select-by-indices '(0 1 2 0 1 3 3 1) '("f" "a" "r" "l")) => '("f" "a" "r" "f" "a" "l" "l" "a"))
(defexamples -grade-up
(-grade-up '< '(3 1 4 2 1 3 3)) => '(1 4 3 0 5 6 2)
(let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-up '< l) l)) => '(1 1 2 3 3 3 4))
(defexamples -grade-down
(-grade-down '< '(3 1 4 2 1 3 3)) => '(2 0 5 6 3 1 4)
(let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-down '< l) l)) => '(4 3 3 3 2 1 1)))
(def-example-group "Set operations" nil
(defexamples -union
(-union '(1 2 3) '(3 4 5)) => '(1 2 3 4 5)

Loading…
Cancel
Save