[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
index.m and rindex.m
From: |
Bill Denney |
Subject: |
index.m and rindex.m |
Date: |
Mon, 30 Oct 2006 23:56:01 -0500 |
User-agent: |
Thunderbird 1.5.0.7 (Windows/20060909) |
Here is a patch to eliminate code duplication and speed up index and
rindex.m.
Bill
scripts/ChangeLog:
2006-10-30 Bill Denney <address@hidden>
* strings/index.m, strings/rindex.m: speed up these functions and
remove code duplication
Index: index.m
===================================================================
RCS file: /cvs/octave/scripts/strings/index.m,v
retrieving revision 1.18
diff -u -r1.18 index.m
--- index.m 10 Oct 2006 16:10:31 -0000 1.18
+++ index.m 31 Oct 2006 04:55:37 -0000
@@ -1,4 +1,4 @@
-## Copyright (C) 1996 Kurt Hornik
+## Copyright (C) 1996, 2006 Kurt Hornik
##
## This file is part of Octave.
##
@@ -19,6 +19,7 @@
## -*- texinfo -*-
## @deftypefn {Function File} {} index (@var{s}, @var{t})
+## @deftypefnx {Function File} {} index (@var{s}, @var{t}, @var{direction})
## Return the position of the first occurrence of the string @var{t} in the
## string @var{s}, or 0 if no occurrence is found. For example,
##
@@ -27,74 +28,101 @@
## @result{} 4
## @end example
##
+## @var{direction} may be either "first" or "last" and you will be given
+## either the first or last element found. rindex is index called with
+## the "last" direction.
+##
## @strong{Caution:} This function does not work for arrays of strings.
+## @seealso{find,rindex}
## @end deftypefn
## Author: Kurt Hornik <address@hidden>
## Adapted-By: jwe
-function n = index (s, t)
+function n = index (s, t, direction)
## This is patterned after the AWK function of the same name.
- if (nargin != 2)
+ if (nargin < 2) || (nargin > 3)
print_usage ();
+ elseif (nargin < 3)
+ direction = "first";
endif
-
- if (!ischar (s) || !ischar (t) || all (size (s) > 1) || all (size (t) > 1) )
+ direction = lower (direction);
+
+ if ! (ischar (s) && ischar (t) && isvector (s) && isvector (t) )
error ("index: expecting string arguments");
+ elseif ! strcmp (direction, {"first" "last"})
+ error ("index: direction must be either \"first\" or \"last\"");
endif
l_s = length (s);
l_t = length (t);
-
+
+ n = 0;
if ( l_s == 0 || l_s < l_t )
## zero length source, or target longer than source
+ ## return 0
v = [];
-
+
elseif ( l_t == 0 )
## zero length target: return first
v = 1;
-
+
elseif ( l_t == 1 )
## length one target: simple find
- v = find (s==t);
-
+ v = find (s==t, 1, direction);
+
elseif ( l_t == 2 )
## length two target: find first at i and second at i+1
- v = find (s (1 : l_s-1) == t (1) & s (2 : l_s) == t (2));
-
+ v = find (s (1:l_s-1) == t(1) & s(2:l_s) == t(2), 1, direction);
+
else
## length three or more: match the first three by find then go through
## the much smaller list to determine which of them are real matches
limit = l_s - l_t + 1;
- v = find (s (1 : limit) == t(1) & s (2 : limit+1) == t (2)
- & s (3 : limit+2) == t(3) );
- endif
-
- if (l_t > 3)
-
- ## force strings to be both row vectors or both column vectors
- if (all (size (s) != size (t)))
- t = t.';
+ v = find (s (1:limit) == t(1)
+ & s (2:limit+1) == t(2)
+ & s (3:limit+2) == t(3));
+ if strcmp (direction, "last")
+ v = v(length(v):-1:1);
endif
-
- ## search index vector for a match
- ind = 0 : l_t - 1;
- n = 0; # return 0 if loop terminates without finding any match
- for idx = 1:length(v)
- if (s (v(idx) + ind) == t)
- n = v(idx);
- break;
+
+ if (l_t > 3)
+
+ ## force strings to be both row vectors or both column vectors
+ if (all (size (s) != size (t)))
+ t = t.';
endif
- endfor
- elseif (length(v) > 0)
- n = v(1);
+ ## search index vector for a match
+ ind = 0:l_t-1;
+ ## return 0 if loop terminates without finding any match
+ for idx = 1:length(v)
+ if (s (v(idx) + ind) == t)
+ n = v(idx);
+ break;
+ endif
+ endfor
+ endif
- else
- n = 0;
+ endif
+ if (n == 0) && ~ isempty (v)
+ ## return the first found if n is not already set and v is not empty
+ n = v(1);
endif
endfunction
+
+## Test the function out
+%!assert(index("astringbstringcstring", "s"), 2)
+%!assert(index("astringbstringcstring", "st"), 2)
+%!assert(index("astringbstringcstring", "str"), 2)
+%!assert(index("astringbstringcstring", "string"), 2)
+
+## test everything out in reverse
+%!assert(index("astringbstringcstring", "s", "last"), 16)
+%!assert(index("astringbstringcstring", "st", "last"), 16)
+%!assert(index("astringbstringcstring", "str", "last"), 16)
+%!assert(index("astringbstringcstring", "string", "last"), 16)
Index: rindex.m
===================================================================
RCS file: /cvs/octave/scripts/strings/rindex.m,v
retrieving revision 1.16
diff -u -r1.16 rindex.m
--- rindex.m 10 Oct 2006 16:10:31 -0000 1.16
+++ rindex.m 31 Oct 2006 04:55:37 -0000
@@ -1,4 +1,4 @@
-## Copyright (C) 1996 Kurt Hornik
+## Copyright (C) 1996, 2006 Kurt Hornik
##
## This file is part of Octave.
##
@@ -28,6 +28,7 @@
## @end example
##
## @strong{Caution:} This function does not work for arrays of strings.
+## @seealso{find,index}
## @end deftypefn
## Author: Kurt Hornik <address@hidden>
@@ -41,60 +42,6 @@
print_usage ();
endif
- if (!ischar (s) || !ischar (t) || all (size (s) > 1) || all (size (t) > 1) )
- error ("rindex: expecting string arguments");
- endif
-
- l_s = length (s);
- l_t = length (t);
-
- if ( l_s == 0 || l_s < l_t )
- ## zero length source, or target longer than source
- v = [];
-
- elseif ( l_t == 0 )
- ## zero length target: return last
- v = l_s;
-
- elseif ( l_t == 1 )
- ## length one target: simple find
- v = find (s==t);
-
- elseif ( l_t == 2 )
- ## length two target: find first at i and second at i+1
- v = find (s (1 : l_s-1) == t (1) & s (2 : l_s) == t (2));
-
- else
- ## length three or more: match the first three by find then go through
- ## the much smaller list to determine which of them are real matches
- limit = l_s - l_t + 1;
- v = find (s (1 : limit) == t(1) & s (2 : limit+1) == t (2)
- & s (3 : limit+2) == t(3) );
- endif
-
- if (l_t > 3)
-
- ## force strings to be both row vectors or both column vectors
- if (all (size (s) != size (t)))
- t = t.';
- endif
-
- ## search index vector for a match
- ind = 0 : l_t - 1;
- n = 0; # return 0 if loop terminates without finding any match
- for idx = length(v):-1:1
- if (s (v(idx) + ind) == t)
- n = v(idx);
- break;
- endif
- endfor
-
- elseif (length(v) > 0)
- n = v(length(v));
-
- else
- n = 0;
-
- endif
+ n = index (s, t, "last");
endfunction
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- index.m and rindex.m,
Bill Denney <=