views:

84

answers:

5

Hi,

I have array and contains 50 values ,

example

london,bluehit,green,lonpark,abc,aab,lonsee

i want to sort as per my preference , i give one argument ,

example if i give arugment as lon then my array should form like

london,lonpark,lonsee,aab,abc,blurhit,green,lonsee ,

so in the above my array output is i gave parameter as lon , so started with my preference character array values and then alphabetical order ,

Advise,

For me the above question is too complex, bcoz i know asort,ksort, asc only , this is

first time am meeting this sort of requirement,

Thanks

+2  A: 

This gets asked a lot. Take a look at using a custom sorting function. From php.net: uksort and usort.

Stephen
Hehe. Kinda fun to think of using a function named uksort() to put London at the top of the list. ;-)
Spudley
Haha haha haha ha! (I would have just typed `lol` but I was foiled by the character limit.)
Stephen
+1  A: 

You can use usort, you can define your own function for sorting the data.

jakenoble
+2  A: 

As the others have said, usort and a bespoke comparator would fit well. Here's an example which has a factory function (in this case, a function which returns a function) which generates comparators (using closures) based on the required prefix.

$subject = explode(',', 'london,bluehit,green,lonpark,abc,aab,lonsee');

function make_comparator($prefix)
{
    return function ($a, $b) use ($prefix) {
        if (strpos($a, $prefix) === 0 && strpos($b, $prefix) !== 0) {
            // $a starts with $prefix (and $b does not), sift up
            return -1;
        } elseif (strpos($a, $prefix) !== 0 && strpos($b, $prefix) === 0) {
            // $b starts with $prefix (and $a does not), sift down
            return 1;
        } else {
            // Otherwise, do a normal string comparison
            return strcmp($a, $b);
        }
    };
}

$sorted = $subject;
usort($sorted, make_comparator('lon'));
var_dump($sorted);

For PHP versions less than 5.3.0 (required for above) you could do something similar:

function prefix_comparator($a, $b, $prefix) {
    if (strpos($a, $prefix) === 0 && strpos($b, $prefix) !== 0) {
        // $a starts with $prefix (and $b does not), sift up
        return -1;
    } elseif (strpos($a, $prefix) !== 0 && strpos($b, $prefix) === 0) {
        // $b starts with $prefix (and $a does not), sift down
        return 1;
    } else {
        // Otherwise, do a normal string comparison
        return strcmp($a, $b);
    }
}

$sort_by_lon = create_function('$a, $b', 'return prefix_comparator($a, $b, "lon");');
$sorted = $subject;
usort($sorted, $sort_by_lon);
var_dump($sorted);

(Apologies for the jargon)

salathe
Hi, salathe , thanks, is there any function call use , bcoz in the above function u used the use keyword,
Bharanikumar
Bharanikumar, the `use` keyword is used to allow an anonymous function access to variables outside of its normal scope (i.e. the closure).
salathe
i executed the above code , i got parse error on this line return function ($a, $b) use ($prefix), program not allowing me to execute.. getting error
Bharanikumar
You're not using PHP 5.3.0 (or newer). The documentation that I pointed you to should have made is clear that version was a requirement. See my edit for older/lower versions of PHP which cannot use closures.
salathe
+2  A: 
  1. replace the string in question with a character with code 1
  2. sort normally
  3. replace the character back

this is it ;)

 $str = "lon";
 $a = array('london', 'bluehit', 'green', 'lonpark', 'abc', 'aab', 'lonsee');
 $b = preg_replace("~^$str~", "\x01", $a);
 sort($b);
 $b = preg_replace('~\x01~', "lon", $b);
 print_r($b);

upd: even simpler is to prepend the string with "\x01" rather than replacing it. This also allows for case-insensitive matching or to match a set of strings:

 $str = "lon";
 $a = array('london', 'bluehit', 'green', 'Lonpark', 'abc', 'aab', 'lonsee');
 $b = preg_replace("~^$str~i", "\x01$0", $a);
 sort($b);
 $b = str_replace('~\x01~', "", $b);
 print_r($b);
stereofrog
is this case sensitive
Bharanikumar
@Bharanikumar: see update
stereofrog
A: 

Here's another possibility for ver. 5.3+:

function pref_sort($arr, $pref, $case_insensitive = true)
{
    $case_insensitive ? natcasesort($arr) : sort($arr);        
    $pref_arr = array_filter($arr, 
        function($val) use ($pref){
            return (strpos(strtolower($val), strtolower($pref)) === 0);
        });
    return array_values($pref_arr + array_diff($arr, $pref_arr));
}

Usage:

$pref_str = 'lon';
$array = array('green', 'Lonpark', 'london', 'bluehit', 'abc', 
               'aab', 'lonsee', 'lon', 'Lon', 'Aab');

// Case-insensitive:
$sorted_array = pref_sort($array, $pref_str);
print_r($sorted_array);
/**
Array
(
    [0] => lon
    [1] => Lon
    [2] => london
    [3] => Lonpark
    [4] => lonsee
    [5] => Aab
    [6] => aab
    [7] => abc
    [8] => bluehit
    [9] => green
)
**/ 

// Case-sensitive:
$sorted_array = pref_sort($array, $pref_str, false);
print_r($sorted_array);
/**
Array
(
    [0] => Lon
    [1] => Lonpark
    [2] => lon
    [3] => london
    [4] => lonsee
    [5] => Aab
    [6] => aab
    [7] => abc
    [8] => bluehit
    [9] => green
)
**/
GZipp