Hi all! I'm having some trouble figuring out the best way to do the following:

Take a list of names (or nicknames), and properly order them in the following fashion:

symbols -> numbers -> letters

For example:

[Aardvark]
[Banana]
{Andrew
Abe Lincoln
Barbossa
Davey Jones
123 Count
21 Jump Street

If they're in an array (in no specific order), what would be the best way to order them properly? I've got the alpha-numeric order with [man]natsort[/man] down, but that puts all the symbols at the end, and I'd like them at the front. Any ideas?

Currently I have these steps:

  1. Query database, order by Name

  2. Put result set into array: $nameArray

  3. Natural Sort array: $nameArray

  4. Reverse array: $nameArray

  5. Loop over array with while based on preg_match for specific characters

  6. Copy those with symbols as first char to $tmp array

  7. Merge the reversal of $tmp and $nameArray together

natsort($orgsArray);
	$orgsArray = array_reverse($orgsArray);
	$i=0;
	$temp = array();
	while(preg_match('~^[[{(]+~', substr($orgsArray[$i], 0, 1)) == true)
	{
		$temp[] = $orgsArray[$i];
		unset($orgsArray[$i]);
		$i++;
	}
	$orgsArray = array_merge(array_reverse($temp), array_reverse($orgsArray));

It works, but I was just wondering if there's a faster or better way.

    It seems to me that a neat approach would be to construct a custom string comparator that follows your comparison rules and then use it with usort().

      Hmm... that's an option. Although I'd have to use [man]uasort[/man] because I use the keys later on..... Thanks for the idea. Have any others?

        This looks kind of ugly, but seems to work, though I'm not sure it would give the desired result when special characters show up in the middle of a string.

        <?php
        function mySort($a, $b)
        {
           if(!ctype_alnum($a[0]) && ctype_alnum($b[0]))
           {
              return -1;
           }
           elseif(ctype_alnum($a[0]) && !ctype_alnum($b[0]))
           {
              return 1;
           }
           elseif(ctype_digit($a[0]) && !ctype_digit($b[0]))
           {
              return 1;
           }
           elseif(!ctype_digit($a[0]) && ctype_digit($b[0]))
           {
              return -1;
           }
           else
           {
              return strcasecmp($a, $b);
           }
        }
        
        $testData = array(
           '[Aardvark]',
           '[Banana]',
           '{Andrew',
           'Abe Lincoln',
           'Barbossa',
           'Davey Jones',
           '123 Count',
           '21 Jump Street',
        );
        shuffle($testData);
        printf("<h3>Before:</h3>\n<pre>%s</pre>\n", print_r($testData, 1));
        uasort($testData, 'mySort');
        printf("<h3>After:</h3>\n<pre>%s</pre>\n", print_r($testData, 1));
        

          I honestly only need the first letter for now. Although, since I'm pulling this stuff out of the database, I might be able to add a flag: sub-organization or not. If it's a sub-org, place it at the top.

            Write a Reply...