Add optional 4th argument to [r]find and [r]index (end of slice).

This commit is contained in:
Guido van Rossum 1997-03-14 04:13:56 +00:00
parent 612316f016
commit 7b7c578616
5 changed files with 99 additions and 43 deletions

View File

@ -103,24 +103,27 @@ This doesn't understand other non-printing characters or escape
sequences. sequences.
\end{funcdesc} \end{funcdesc}
\begin{funcdesc}{find}{s\, sub\optional{\, start}} \begin{funcdesc}{find}{s\, sub\optional{\, start\optional{\,end}}}
Return the lowest index in \var{s} not smaller than \var{start} where the Return the lowest index in \var{s} not smaller than \var{start} and not
substring \var{sub} is found. Return \code{-1} when \var{sub} greater than \var{end} where the substring \var{sub} is found. Return
does not occur as a substring of \var{s} with index at least \var{start}. \code{-1} when \var{sub} does not occur as a substring of \var{s} with
index at least \var{start} and less than \var{end}.
If \var{start} is omitted, it defaults to \code{0}. If \var{start} is If \var{start} is omitted, it defaults to \code{0}. If \var{start} is
negative, \code{len(\var{s})} is added. negative, \code{len(\var{s})} is added.
If \var{end} is omitted, it defaults to \code{len(\var{s})}. If
\var{end} is negative, \code{len(\var{s})} is added.
\end{funcdesc} \end{funcdesc}
\begin{funcdesc}{rfind}{s\, sub\optional{\, start}} \begin{funcdesc}{rfind}{s\, sub\optional{\, start\optional{\,end}}}
Like \code{find} but find the highest index. Like \code{find} but find the highest index.
\end{funcdesc} \end{funcdesc}
\begin{funcdesc}{index}{s\, sub\optional{\, start}} \begin{funcdesc}{index}{s\, sub\optional{\, start\optional{\,end}}}
Like \code{find} but raise \code{ValueError} when the substring is Like \code{find} but raise \code{ValueError} when the substring is
not found. not found.
\end{funcdesc} \end{funcdesc}
\begin{funcdesc}{rindex}{s\, sub\optional{\, start}} \begin{funcdesc}{rindex}{s\, sub\optional{\, start\optional{\,end}}}
Like \code{rfind} but raise \code{ValueError} when the substring is Like \code{rfind} but raise \code{ValueError} when the substring is
not found. not found.
\end{funcdesc} \end{funcdesc}

View File

@ -103,24 +103,27 @@ This doesn't understand other non-printing characters or escape
sequences. sequences.
\end{funcdesc} \end{funcdesc}
\begin{funcdesc}{find}{s\, sub\optional{\, start}} \begin{funcdesc}{find}{s\, sub\optional{\, start\optional{\,end}}}
Return the lowest index in \var{s} not smaller than \var{start} where the Return the lowest index in \var{s} not smaller than \var{start} and not
substring \var{sub} is found. Return \code{-1} when \var{sub} greater than \var{end} where the substring \var{sub} is found. Return
does not occur as a substring of \var{s} with index at least \var{start}. \code{-1} when \var{sub} does not occur as a substring of \var{s} with
index at least \var{start} and less than \var{end}.
If \var{start} is omitted, it defaults to \code{0}. If \var{start} is If \var{start} is omitted, it defaults to \code{0}. If \var{start} is
negative, \code{len(\var{s})} is added. negative, \code{len(\var{s})} is added.
If \var{end} is omitted, it defaults to \code{len(\var{s})}. If
\var{end} is negative, \code{len(\var{s})} is added.
\end{funcdesc} \end{funcdesc}
\begin{funcdesc}{rfind}{s\, sub\optional{\, start}} \begin{funcdesc}{rfind}{s\, sub\optional{\, start\optional{\,end}}}
Like \code{find} but find the highest index. Like \code{find} but find the highest index.
\end{funcdesc} \end{funcdesc}
\begin{funcdesc}{index}{s\, sub\optional{\, start}} \begin{funcdesc}{index}{s\, sub\optional{\, start\optional{\,end}}}
Like \code{find} but raise \code{ValueError} when the substring is Like \code{find} but raise \code{ValueError} when the substring is
not found. not found.
\end{funcdesc} \end{funcdesc}
\begin{funcdesc}{rindex}{s\, sub\optional{\, start}} \begin{funcdesc}{rindex}{s\, sub\optional{\, start\optional{\,end}}}
Like \code{rfind} but raise \code{ValueError} when the substring is Like \code{rfind} but raise \code{ValueError} when the substring is
not found. not found.
\end{funcdesc} \end{funcdesc}

View File

@ -120,15 +120,17 @@ def joinfields(words, sep = ' '):
return res[len(sep):] return res[len(sep):]
# Find substring, raise exception if not found # Find substring, raise exception if not found
def index(s, sub, i = 0): def index(s, sub, i = 0, last=None):
res = find(s, sub, i) if last == None: last = len(s)
res = find(s, sub, i, last)
if res < 0: if res < 0:
raise ValueError, 'substring not found in string.index' raise ValueError, 'substring not found in string.index'
return res return res
# Find last substring, raise exception if not found # Find last substring, raise exception if not found
def rindex(s, sub, i = 0): def rindex(s, sub, i = 0, last=None):
res = rfind(s, sub, i) if last == None: last = len(s)
res = rfind(s, sub, i, last)
if res < 0: if res < 0:
raise ValueError, 'substring not found in string.index' raise ValueError, 'substring not found in string.index'
return res return res
@ -149,20 +151,34 @@ def count(s, sub, i = 0):
return r return r
# Find substring, return -1 if not found # Find substring, return -1 if not found
def find(s, sub, i = 0): def find(s, sub, i = 0, last=None):
if i < 0: i = max(0, i + len(s)) Slen = len(s) # cache this value, for speed
if last == None:
last = Slen
elif last < 0:
last = max(0, last + Slen)
elif last > Slen:
last = Slen
if i < 0: i = max(0, i + Slen)
n = len(sub) n = len(sub)
m = len(s) + 1 - n m = last + 1 - n
while i < m: while i < m:
if sub == s[i:i+n]: return i if sub == s[i:i+n]: return i
i = i+1 i = i+1
return -1 return -1
# Find last substring, return -1 if not found # Find last substring, return -1 if not found
def rfind(s, sub, i = 0): def rfind(s, sub, i = 0, last=None):
if i < 0: i = max(0, i + len(s)) Slen = len(s) # cache this value, for speed
if last == None:
last = Slen
elif last < 0:
last = max(0, last + Slen)
elif last > Slen:
last = Slen
if i < 0: i = max(0, i + Slen)
n = len(sub) n = len(sub)
m = len(s) + 1 - n m = last + 1 - n
r = -1 r = -1
while i < m: while i < m:
if sub == s[i:i+n]: r = i if sub == s[i:i+n]: r = i

View File

@ -120,15 +120,17 @@ def joinfields(words, sep = ' '):
return res[len(sep):] return res[len(sep):]
# Find substring, raise exception if not found # Find substring, raise exception if not found
def index(s, sub, i = 0): def index(s, sub, i = 0, last=None):
res = find(s, sub, i) if last == None: last = len(s)
res = find(s, sub, i, last)
if res < 0: if res < 0:
raise ValueError, 'substring not found in string.index' raise ValueError, 'substring not found in string.index'
return res return res
# Find last substring, raise exception if not found # Find last substring, raise exception if not found
def rindex(s, sub, i = 0): def rindex(s, sub, i = 0, last=None):
res = rfind(s, sub, i) if last == None: last = len(s)
res = rfind(s, sub, i, last)
if res < 0: if res < 0:
raise ValueError, 'substring not found in string.index' raise ValueError, 'substring not found in string.index'
return res return res
@ -149,20 +151,34 @@ def count(s, sub, i = 0):
return r return r
# Find substring, return -1 if not found # Find substring, return -1 if not found
def find(s, sub, i = 0): def find(s, sub, i = 0, last=None):
if i < 0: i = max(0, i + len(s)) Slen = len(s) # cache this value, for speed
if last == None:
last = Slen
elif last < 0:
last = max(0, last + Slen)
elif last > Slen:
last = Slen
if i < 0: i = max(0, i + Slen)
n = len(sub) n = len(sub)
m = len(s) + 1 - n m = last + 1 - n
while i < m: while i < m:
if sub == s[i:i+n]: return i if sub == s[i:i+n]: return i
i = i+1 i = i+1
return -1 return -1
# Find last substring, return -1 if not found # Find last substring, return -1 if not found
def rfind(s, sub, i = 0): def rfind(s, sub, i = 0, last=None):
if i < 0: i = max(0, i + len(s)) Slen = len(s) # cache this value, for speed
if last == None:
last = Slen
elif last < 0:
last = max(0, last + Slen)
elif last > Slen:
last = Slen
if i < 0: i = max(0, i + Slen)
n = len(sub) n = len(sub)
m = len(s) + 1 - n m = last + 1 - n
r = -1 r = -1
while i < m: while i < m:
if sub == s[i:i+n]: r = i if sub == s[i:i+n]: r = i

View File

@ -33,6 +33,12 @@ PERFORMANCE OF THIS SOFTWARE.
#include "Python.h" #include "Python.h"
#ifdef HAVE_LIMITS_H
#include <limits.h>
#else
#define INT_MAX 2147483647
#endif
#include <ctype.h> #include <ctype.h>
/* XXX This file assumes that the <ctype.h> is*() functions /* XXX This file assumes that the <ctype.h> is*() functions
XXX are defined for all 8-bit characters! */ XXX are defined for all 8-bit characters! */
@ -286,11 +292,17 @@ strop_find(self, args)
PyObject *args; PyObject *args;
{ {
char *s, *sub; char *s, *sub;
int len, n, i = 0; int len, n, i = 0, last = INT_MAX;
if (!PyArg_ParseTuple(args, "s#s#|i", &s, &len, &sub, &n, &i)) if (!PyArg_ParseTuple(args, "s#s#|ii", &s, &len, &sub, &n, &i, &last))
return NULL; return NULL;
if (last > len)
last = len;
if (last < 0)
last += len;
if (last < 0)
last = 0;
if (i < 0) if (i < 0)
i += len; i += len;
if (i < 0) if (i < 0)
@ -299,8 +311,8 @@ strop_find(self, args)
if (n == 0) if (n == 0)
return PyInt_FromLong((long)i); return PyInt_FromLong((long)i);
len -= n; last -= n;
for (; i <= len; ++i) for (; i <= last; ++i)
if (s[i] == sub[0] && if (s[i] == sub[0] &&
(n == 1 || memcmp(&s[i+1], &sub[1], n-1) == 0)) (n == 1 || memcmp(&s[i+1], &sub[1], n-1) == 0))
return PyInt_FromLong((long)i); return PyInt_FromLong((long)i);
@ -316,20 +328,26 @@ strop_rfind(self, args)
{ {
char *s, *sub; char *s, *sub;
int len, n, j; int len, n, j;
int i = 0; int i = 0, last = INT_MAX;
if (!PyArg_ParseTuple(args, "s#s#|i", &s, &len, &sub, &n, &i)) if (!PyArg_ParseTuple(args, "s#s#|ii", &s, &len, &sub, &n, &i, &last))
return NULL; return NULL;
if (last > len)
last = len;
if (last < 0)
last += len;
if (last < 0)
last = 0;
if (i < 0) if (i < 0)
i += len; i += len;
if (i < 0) if (i < 0)
i = 0; i = 0;
if (n == 0) if (n == 0)
return PyInt_FromLong((long)len); return PyInt_FromLong((long)last);
for (j = len-n; j >= i; --j) for (j = last-n; j >= i; --j)
if (s[j] == sub[0] && if (s[j] == sub[0] &&
(n == 1 || memcmp(&s[j+1], &sub[1], n-1) == 0)) (n == 1 || memcmp(&s[j+1], &sub[1], n-1) == 0))
return PyInt_FromLong((long)j); return PyInt_FromLong((long)j);
@ -663,7 +681,7 @@ strop_atof(self, args)
errno = 0; errno = 0;
PyFPE_START_PROTECT("strop_atof", return 0) PyFPE_START_PROTECT("strop_atof", return 0)
x = strtod(s, &end); x = strtod(s, &end);
PyFPE_END_PROTECT PyFPE_END_PROTECT(x)
while (*end && isspace(Py_CHARMASK(*end))) while (*end && isspace(Py_CHARMASK(*end)))
end++; end++;
if (*end != '\0') { if (*end != '\0') {