emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* [Patch] Table lookup functions: director's cut
@ 2012-10-15  7:25 Jarmo Hurri
  2012-10-26  8:24 ` Jarmo Hurri
  0 siblings, 1 reply; 2+ messages in thread
From: Jarmo Hurri @ 2012-10-15  7:25 UTC (permalink / raw)
  To: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 1658 bytes --]


Greetings.

Here is the newest version of the patch implementing table lookup
functions.

First, to see what these little functions can do, take a look at

http://orgmode.org/worg/org-tutorials/org-lookups.html

Please note that the patch is not in the official git repository yet, so
you can not replicate the examples in the tutorial. When and if I get
the word that the patch has been applied, I will add a link to the
tutorial in the main tutorial page on Worg.

A few notes on the patch:

1. There is now a third lookup function org-lookup-all, which I thought
   would be a very useful addition.

2. The three lookup functions are still defined by calls to a single
   macro. Heck, one of the advertised reasons for using Lisp are its
   macro capabilities, so I could not resist. The generated
   documentation strings now contain a reference to the macro, so users
   can locate the macro in org-table.el.

3. CL is no longer used in the implementation. I decided to implement
   the search using a while control structure. I wanted to do a tail
   recursive implementation, but then found out that Emacs Lisp does not
   do tail-call optimization. If you'd like me to use a different
   control structure (for some reason), I can change it.

4. Technically R-LIST is now an optional parameter in the lookup
   functions, because if it is nil, the matching value from S-LIST is
   returned directly. I decided not to define it to be an optional
   parameter, because that would simply look weird to a first-time user:
   the default use would then be to find a value and return the same
   value, which would not make much sense.

Have fun!

Jarmo


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: table lookup functions --]
[-- Type: text/x-patch, Size: 6531 bytes --]

From dfa552f2e8b61ce301900dcce7da92d4f8f0854a Mon Sep 17 00:00:00 2001
From: Jarmo Hurri <jarmo.hurri@syk.fi>
Date: Mon, 15 Oct 2012 09:54:24 +0300
Subject: [PATCH] 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
---
 doc/org.texi      |   50 ++++++++++++++++++++++++++++++++++++++++++++++++--
 lisp/org-table.el |   32 ++++++++++++++++++++++++++++++++
 2 files changed, 80 insertions(+), 2 deletions(-)

diff --git a/doc/org.texi b/doc/org.texi
index c8f0afb..6d8f59a 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:
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [Patch] Table lookup functions: director's cut
  2012-10-15  7:25 [Patch] Table lookup functions: director's cut Jarmo Hurri
@ 2012-10-26  8:24 ` Jarmo Hurri
  0 siblings, 0 replies; 2+ messages in thread
From: Jarmo Hurri @ 2012-10-26  8:24 UTC (permalink / raw)
  To: emacs-orgmode


Greetings.

I got an email saying that the patch has now been committed to git. I
also added a link to the tutorial on the tutorial index page at

http://orgmode.org/worg/org-tutorials/

All the best.

Jarmo

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2012-10-26  8:25 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-10-15  7:25 [Patch] Table lookup functions: director's cut Jarmo Hurri
2012-10-26  8:24 ` Jarmo Hurri

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).