Re: Custom Usort Function

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, January 23, 2006 6:53 pm, Matt Palermo wrote:
> I'm try to sort a list of items using a usort function.  Basically, I
> want
> it to sort in this order:
>
> Numbers (0-9)
> Letters (Aa-Zz)
> Other (anything else)
>
> To explain a little further, I want anything that starts with a number
> to
> show up first in the sorted list, then anything that starts with a
> letter,
> and finally anything that starts with some other character.  My usort
> function I'm using now gives me results close to this, but it sorts it
> as
> follows (which is wrong for what I need):
>
> Numbers (0-9)
> Other (anything else)
> Letters (Aa-Zz)
>
> They are all sorted properly alphabetically, but not in the group
> order that
> I need them in.  Here is the usort function I'm using right now:
>
>
> function myUsort($x, $y)
>  {
>   if(strtolower($x) == strtolower($y)) return 0;
>   if(strtolower($x) < strtolower($y)) return -1;
>   return 1;
>  }

The issue with previous posts is that they will only look at the first
character, unless I'm mis-reading them.

So:
__a
_a_
will not sort the way you want.

Here is my take on it:

function myUsort($x, $y){
  //ignore case (I chose upper only because I know the ASCII values)
  $x = strtoupper($x);
  $y = strtoupper($y);
  $xlen = strlen($x);
  $ylen = strlen($y);
  $len = min($xlen, $ylen);
  for ($i = 0; $i < $len; $i++){
    $xi = $x[$i]; $yi = $y[$i];
    $xc = ord($xi); $yc = ord($yi);
    if ($xi == $yi) continue;

    //handle a-z and 0-9 normally:
    elseif (    (65 <= $xc && $xc <=90 || 48 <= $xc && $xc <= 57)
             && (65 <= $yc && $yc < 90 || 48 <= $yc && $yc <= 57)
           )
      return strcasecmp($xc, $yc);

    //either $xi or $yi is out of the normal range and is "big"...

    //$xc is the oddball character
    elseif ($xc < 48 || $xc > 57 && $xc < 65 || $xc > 90) return 1;

    //$yc must be the oddball character
    else return -1;
  }

  //The strings completely matched, up to the end of one of them:
  if ($xlen < $ylen) return -1;
  elseif ($xlen > $ylen) return 1;
  else return 0;
}

I'm not promising I got the -1 / 1 / 0 ordering correct for < > == but
this should work.

Probably not the fastest, particularly for long strings, as PHP for
loops are not speedy...

-- 
Like Music?
http://l-i-e.com/artists.htm

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php


[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux