Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Reverse the order of an array?



 --- Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:

> There are already a number of inconsistencies between glob qualifiers
> and parameter flags in this regard.  Order matters in glob
> qualifiers;
> e.g. (n) by itself is numeric sorting (which we don't yet do in
> arrays),
> (no) is an error, and (on) means sort by name.  In parameter flags
> (i)
> by itself is meaningless, but both (io) and (oi) mean to sort case-
> independently (an option that we don't have in the glob qualifiers).
> 
> Also, directory order is not likely to have been carefully crafted by
> the user the way array ordering is.  The main use of pure directory
> order would be to avoid sorting when there are a large number of
> files.

I'll not worry about about directory order then. Is there any demand
for case insensitive glob sorting? (i) is free.

Seeing as you mentioned it I've added the numeric ordering. It'll save
you having to rescue (n) from being used for something else again (as
you did in 16350). This also means that `(oin)' should result in
case-insensitive numeric ordering.

Could someone better at C and perhaps more awake than me please take a
look at instrpcmp(). Is there a cleaner way I can get a pointer to a
pointer of the VARARRs to pass on to nstrpcmp()? I can avoid the cast
with `char (*e)[] = &c;' but the SGI compiler prints a warning for
that. I was hoping to avoid the e and f variables.

I've swiped notstrcmp() out of glob.c for this so the patch is longer
than it really is. I hope nobody minds about that function's move and
rename? Patch includes documentation for this and the new (a) flag.

Oliver

--- Src/subst.c.before	Wed Feb 20 19:34:54 2002
+++ Src/subst.c	Thu Feb 21 23:44:14 2002
@@ -540,6 +540,72 @@
 }
 
 /**/
+int
+nstrpcmp(const void *a, const void *b)
+{
+    char *c = *(char **)a, *d = *(char **)b;
+    int cmp;
+
+#ifdef HAVE_STRCOLL
+    cmp = strcoll(c, d);
+#endif
+    for (; *c == *d && *c; c++, d++);
+#ifndef HAVE_STRCOLL
+    cmp = (int)STOUC(*c) - (int)STOUC(*d);
+#endif
+    if (idigit(*c) || idigit(*d)) {
+	for (; c > *(char **)b && idigit(c[-1]); c--, d--);
+	if (idigit(*c) && idigit(*d)) {
+	    while (*c == '0')
+		c++;
+	    while (*d == '0')
+		d++;
+	    for (; idigit(*c) && *c == *d; c++, d++);
+	    if (idigit(*c) || idigit(*d)) {
+		cmp = (int)STOUC(*c) - (int)STOUC(*d);
+		while (idigit(*c) && idigit(*d))
+		    c++, d++;
+		if (idigit(*c) && !idigit(*d))
+		    return 1;
+		if (idigit(*d) && !idigit(*c))
+		    return -1;
+	    }
+	}
+    }
+    return cmp;
+}
+
+/**/
+int
+invnstrpcmp(const void *a, const void *b)
+{
+    return -nstrpcmp(a, b);
+}
+
+/**/
+int
+instrpcmp(const void *a, const void *b)
+{
+    VARARR(char, c, strlen(*(char **) a) + 1);
+    VARARR(char, d, strlen(*(char **) b) + 1);
+    char **e = (char **)&c;
+    char **f = (char **)&d;
+    char *s, *t;
+
+    for (s = *(char **) a, t = c; (*t++ = tulower(*s++)););
+    for (s = *(char **) b, t = d; (*t++ = tulower(*s++)););
+
+    return nstrpcmp(&e, &f);
+}
+
+/**/
+int
+invinstrpcmp(const void *a, const void *b)
+{
+    return -instrpcmp(a, b);
+}
+
+/**/
 static char *
 dopadding(char *str, int prenum, int postnum, char *preone, char
*postone, char *premul, char *postmul)
 {
@@ -773,7 +839,7 @@
     Value v = NULL;
     int flags = 0;
     int flnum = 0;
-    int sortit = 0, casind = 0, indord = 0;
+    int sortit = 0, casind = 0, numord = 0, indord = 0;
     int unique = 0;
     int casmod = 0;
     int quotemod = 0, quotetype = 0, quoteerr = 0;
@@ -881,6 +947,9 @@
 		case 'i':
 		    casind = 1;
 		    break;
+		case 'n':
+		    numord = 1;
+		    break;
 		case 'a':
 		    indord = 1;
 		    break;
@@ -1021,7 +1090,7 @@
 	}
     }
     if (sortit)
-	sortit += (casind << 1);
+	sortit += (casind << 1) + (numord << 2);
 
     if (!premul)
 	premul = " ";
@@ -1913,7 +1982,8 @@
 		}
 	    } else {
 		static CompareFn sortfn[] = {
-		    strpcmp, invstrpcmp, cstrpcmp, invcstrpcmp
+		    strpcmp, invstrpcmp, cstrpcmp, invcstrpcmp,
+		    nstrpcmp, invnstrpcmp, instrpcmp, invinstrpcmp
 		};
 
 		i = arrlen(aval);
--- Src/glob.c.before	Thu Feb 21 23:25:39 2002
+++ Src/glob.c	Thu Feb 21 23:44:14 2002
@@ -854,7 +854,10 @@
     for (i = gf_nsorts, s = gf_sortlist; i; i--, s++) {
 	switch (*s & ~GS_DESC) {
 	case GS_NAME:
-	    r = notstrcmp(&a->name, &b->name);
+	    if (gf_numsort)
+	    	r = nstrpcmp(&b->name, &a->name);
+	    else
+	    	r = strpcmp(&b->name, &a->name);
 	    break;
 	case GS_DEPTH:
 	    {
@@ -1609,46 +1612,6 @@
     free(matchbuf);
 
     restore_globstate(saved);
-}
-
-/* Return the order of two strings, taking into account *
- * possible numeric order if NUMERICGLOBSORT is set.    *
- * The comparison here is reversed.                     */
-
-/**/
-static int
-notstrcmp(char **a, char **b)
-{
-    char *c = *b, *d = *a;
-    int cmp;
-
-#ifdef HAVE_STRCOLL
-    cmp = strcoll(c, d);
-#endif
-    for (; *c == *d && *c; c++, d++);
-#ifndef HAVE_STRCOLL
-    cmp = (int)STOUC(*c) - (int)STOUC(*d);
-#endif
-    if (gf_numsort && (idigit(*c) || idigit(*d))) {
-	for (; c > *b && idigit(c[-1]); c--, d--);
-	if (idigit(*c) && idigit(*d)) {
-	    while (*c == '0')
-		c++;
-	    while (*d == '0')
-		d++;
-	    for (; idigit(*c) && *c == *d; c++, d++);
-	    if (idigit(*c) || idigit(*d)) {
-		cmp = (int)STOUC(*c) - (int)STOUC(*d);
-		while (idigit(*c) && idigit(*d))
-		    c++, d++;
-		if (idigit(*c) && !idigit(*d))
-		    return 1;
-		if (idigit(*d) && !idigit(*c))
-		    return -1;
-	    }
-	}
-    }
-    return cmp;
 }
 
 /* Return the trailing character for marking file types */
--- Doc/Zsh/expn.yo.before      Thu Feb 21 23:44:08 2002
+++ Doc/Zsh/expn.yo     Thu Feb 21 23:44:14 2002
@@ -620,6 +620,11 @@
 example by using `tt(${(AA)=)var(name)tt(=)...tt(})' to activate
 field splitting, when creating an associative array.
 )
+item(tt(a))(
+With tt(o) or tt(O), sort in array index order. Note that `tt(oa)' is
+therefore equivalent to the default but `tt(Oa)' is useful for
+obtaining an array's elements in reverse order.
+)
 item(tt(c))(
 With tt(${#)var(name)tt(}), count the total number of characters in an
array,
 as if the elements were concatenated with spaces between them.
@@ -660,6 +665,9 @@
 )
 item(tt(O))(
 Sort the resulting words in descending order.
+)
+item(tt(n))(
+With tt(o) or tt(O), sort numerically.
 )
 item(tt(P))(
 This forces the value of the parameter var(name) to be interpreted as
a


__________________________________________________
Do You Yahoo!?
Everything you'll ever need on one web page
from News and Sport to Email and Music Charts
http://uk.my.yahoo.com



Messages sorted by: Reverse Date, Date, Thread, Author