summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJarmo Hurri <jarmo.hurri@syk.fi>2012-10-15 09:54:24 +0300
committerBastien Guerry <bzg@altern.org>2012-10-24 14:59:33 +0200
commite375cfd834b8cd9acc47b396578f32ca2cca6632 (patch)
treec78e8c70ee79d406684baf0a2c6a3abe710753f2
parent1886af4337e802806ff8873822ccbd2e3763aa07 (diff)
downloadorg-mode-e375cfd834b8cd9acc47b396578f32ca2cca6632.tar.gz
Table lookup functions
* lisp/org-table.el: added macro org-define-lookup-function and the calls to this macro that generate the lookup functions org-lookup-first, org-lookup-last and org-lookup-all * doc/org.texi: documented lookup functions
-rw-r--r--doc/org.texi50
-rw-r--r--lisp/org-table.el32
2 files changed, 80 insertions, 2 deletions
diff --git a/doc/org.texi b/doc/org.texi
index 4d20e06..4de6bfe 100644
--- a/doc/org.texi
+++ b/doc/org.texi
@@ -378,6 +378,7 @@ The spreadsheet
* Durations and time values:: How to compute durations and time values
* Field and range formulas:: Formula for specific (ranges of) fields
* Column formulas:: Formulas valid for an entire column
+* Lookup functions:: Lookup functions for searching tables
* Editing and debugging formulas:: Fixing formulas
* Updating the table:: Recomputing all dependent fields
* Advanced features:: Field and column names, parameters and automatic recalc
@@ -2397,6 +2398,7 @@ formula, moving these references by arrow keys
* Durations and time values:: How to compute durations and time values
* Field and range formulas:: Formula for specific (ranges of) fields
* Column formulas:: Formulas valid for an entire column
+* Lookup functions:: Lookup functions for searching tables
* Editing and debugging formulas:: Fixing formulas
* Updating the table:: Recomputing all dependent fields
* Advanced features:: Field and column names, parameters and automatic recalc
@@ -2782,7 +2784,7 @@ can also be used to assign a formula to some but not all fields in a row.
Named field, see @ref{Advanced features}.
@end table
-@node Column formulas, Editing and debugging formulas, Field and range formulas, The spreadsheet
+@node Column formulas, Lookup functions, Field and range formulas, The spreadsheet
@subsection Column formulas
@cindex column formula
@cindex formula, for table column
@@ -2821,7 +2823,51 @@ stores it. With a numeric prefix argument(e.g.@: @kbd{C-5 C-c =}) the command
will apply it to that many consecutive fields in the current column.
@end table
-@node Editing and debugging formulas, Updating the table, Column formulas, The spreadsheet
+@node Lookup functions, Editing and debugging formulas, Column formulas, The spreadsheet
+@subsection Lookup functions
+@cindex lookup functions in tables
+@cindex table lookup functions
+
+Org has three predefined Emacs Lisp functions for lookups in tables.
+@table @code
+@item (org-lookup-first VAL S-LIST R-LIST &optional PREDICATE)
+@findex org-lookup-first
+Searches for the first element @code{S} in list @code{S-LIST} for which
+@lisp
+(PREDICATE VAL S)
+@end lisp
+is @code{t}; returns the value from the corresponding position in list
+@code{R-LIST}. The default @code{PREDICATE} is @code{equal}. Note that the
+parameters @code{VAL} and @code{S} are passed to @code{PREDICATE} in the same
+order as the correspoding parameters are in the call to
+@code{org-lookup-first}, where @code{VAL} precedes @code{S-LIST}. If
+@code{R-LIST} is @code{nil}, the matching element @code{S} of @code{S-LIST}
+is returned.
+@item (org-lookup-last VAL S-LIST R-LIST &optional PREDICATE)
+@findex org-lookup-last
+Similar to @code{org-lookup-first} above, but searches for the @i{last}
+element for which @code{PREDICATE} is @code{t}.
+@item (org-lookup-all VAL S-LIST R-LIST &optional PREDICATE)
+@findex org-lookup-all
+Similar to @code{org-lookup-first}, but searches for @i{all} elements for
+which @code{PREDICATE} is @code{t}, and returns @i{all} corresponding
+values. This function can not be used by itself in a formula, because it
+returns a list of values. However, powerful lookups can be built when this
+function is combined with other Emacs Lisp functions.
+@end table
+
+If the ranges used in these functions contain empty fields, the @code{E} mode
+for the formula should usually be specified: otherwise empty fields will not be
+included in @code{S-LIST} and/or @code{R-LIST} which can, for example, result
+in an incorrect mapping from an element of @code{S-LIST} to the corresponding
+element of @code{R-LIST}.
+
+These three functions can be used to implement associative arrays, count
+matching cells, rank results, group data etc. For practical examples
+see @uref{http://orgmode.org/worg/org-tutorials/org-lookups.html, this
+tutorial on Worg}.
+
+@node Editing and debugging formulas, Updating the table, Lookup functions, The spreadsheet
@subsection Editing and debugging formulas
@cindex formula editing
@cindex editing, of table formulas
diff --git a/lisp/org-table.el b/lisp/org-table.el
index 0555041..33fcb41 100644
--- a/lisp/org-table.el
+++ b/lisp/org-table.el
@@ -4875,6 +4875,38 @@ list of the fields in the rectangle ."
(org-table-get-range (match-string 0 form) tbeg 1))
form)))))))))
+(defmacro org-define-lookup-function (mode)
+ (let ((mode-str (symbol-name mode))
+ (first-p (equal mode 'first))
+ (all-p (equal mode 'all)))
+ (let ((plural-str (if all-p "s" "")))
+ `(defun ,(intern (format "org-lookup-%s" mode-str)) (val s-list r-list &optional predicate)
+ ,(format "Find %s occurrence%s of VAL in S-LIST; return corresponding element%s of R-LIST.
+If R-LIST is nil, return matching element%s of S-LIST.
+If PREDICATE is not nil, use it instead of `equal' to match VAL.
+Matching is done by (PREDICATE VAL S), where S is an element of S-LIST.
+This function is generated by a call to the macro `org-define-lookup-function'."
+ mode-str plural-str plural-str plural-str)
+ (let ,(let ((lvars '((p (or predicate 'equal))
+ (sl s-list)
+ (rl (or r-list s-list))
+ (ret nil))))
+ (if first-p (add-to-list 'lvars '(match-p nil)))
+ lvars)
+ (while ,(if first-p '(and (not match-p) sl) 'sl)
+ (progn
+ (if (funcall p val (car sl))
+ (progn
+ ,(if first-p '(setq match-p t))
+ (let ((rval (car rl)))
+ (setq ret ,(if all-p '(append ret (list rval)) 'rval)))))
+ (setq sl (cdr sl) rl (cdr rl))))
+ ret)))))
+
+(org-define-lookup-function first)
+(org-define-lookup-function last)
+(org-define-lookup-function all)
+
(provide 'org-table)
;; Local variables: