6

I want to sort arrays by key in php, but the alphabet that I'm using is not the normal English alphabet -- it's a self-created alphabet. Is this possible?

My alphabet is:

$alphabet = "AjawbpfmnrhHxXsSqkgtTdD =";

The array is like this:

Array (
   [=k_0] => Array(
       [0] => DI.3,2 &dwA-nTr& @Hrw@
       [1] => mA
       [2] => =k
       [3] => Sfj,t
       [4] => =k
       [5] => pXr
       )
   [aA_2] => Array(
       [0] => DI.7,4 &dwA-nTr& @Hrw-smA-tA,wj@
       [1] => snD
       [2] => aA
       [3] => Sfj,t
       [4] => jt
       [5] => jt,w
       )
  [sqA_1] => Array(
       [0] => DI.6,18 &dwA-nTr& @nswt@
       [1] => ra
       [2] => sqA
       [3] => Sfj,t
       [4] => =s
       [5] => r
       )
   );

So if I sort this array following my alphabet then the array with the key [=k_0] should be at the end.

4
  • What do you mean by self created alphabet? How do you map those? don't you still need an integer to represent it? Commented Jun 14, 2011 at 21:49
  • any example of such keys, maybe? Commented Jun 14, 2011 at 21:50
  • the alphabet is $alphabet = "AjawbpfmnrhHxXsSqkgtTdD" Commented Jun 14, 2011 at 22:28
  • the alphabet is $alphabet = "AjawbpfmnrhHxXsSqkgtTdD ="; the array is like this: Array ([=k_0] => Array([0] => DI.3,2 &dwA-nTr& @Hrw@ [1] => mA [2] => =k [3] => Sfj,t [4] => =k [5] => pXr ) [aA_2] => Array( [0] => DI.7,4 &dwA-nTr& @Hrw-smA-tA,wj@ [1] => snD [2] => aA [3] => Sfj,t [4] => jt [5] => jt,w ) [sqA_1] => Array( [0] => DI.6,18 &dwA-nTr& @nswt@ [1] => ra [2] => sqA [3] => Sfj,t [4] => =s [5] => r ) ); so if i sort this array following my alphabet the array with the key [=k_0] should be at the end. Commented Jun 14, 2011 at 22:37

5 Answers 5

7

You can use the usort() function and provide your own sorting logic.

See php.net for an example.

Edit: use uksort, not usort. See http://www.php.net/manual/en/function.uksort.php. Thanks @Darien!

A slightly modified example from php.net - the original code with an $alphabet mapping added:

function cmp($a, $b)
{
    // custom sort order - just swapps 2 and 3.
    $alphabet = array (1 => 1, 2 => 3, 3 => 2, 4 => 4, 5 => 5, 6=> 6);

    if ($alphabet[$a] == $alphabet[$b]) {
        return 0;
    }
    return ($alphabet[$a] < $alphabet[$b]) ? -1 : 1;
}

$a = array(3 => 'c' , 2 => 'b', 5 => 'e', 6 => 'f', 1=>'a');
uksort($a, "cmp");

foreach ($a as $key => $value) {
    echo "$key: $value\n";
}
Sign up to request clarification or add additional context in comments.

7 Comments

Yes - OP has custom requirements not directly covered by regular functionality. Without detailed information, usort is a great starting point.
I think you mean uksort(). @Oz: Yes, I think so, since the other alternative--creating a custom locale--strikes me as an incredible amount of effort/overkill.
Question was about sorting by custom alphabet, not just about 'how to sort array'. It's not an answer, so -1.
@OZ_: It is a positive route to take given the information provided. If you can think of a better approach, go ahead and post it instead.
the above function works of course but in my case the keys are strings which have to be sorted according to a preset alphabet for example "sleep" => "evening" should come after "awake" => "morning", giving array("awake"=>"morning", "sleep" => "evening"); but this must now be accomplished not with the english alphabet but with another alphabet (AjawbpfmnrhHxXsSqkgtTdD=)
|
0

Given your $alphabet = "AjawbpfmnrhHxXsSqkgtTdD";, and assuming that A<j<a, etc, per your comment, transform each key in the alternative alphabet to a series in the known alphabet, e.g. use a mapping like:

  your alphabet: AjawbpfmnrhHxXsSqkgtTdD
 'real'alphabet: abcdefghijklmnopqrstuvw

So the key 'Ajaw' => 'abcd', and 'fmnr' => 'ghij', etc. This then turns your keys into something you can sort using conventional php functions. You'd need some way to handle characeters not present in your original alphabet though.

Something like that might work - you'd need two transform functions (from your alphabet to 'real' alphabet and vice versa), and then a comparator for e.g. uksort.

My two cents - thanks for clarifying the original question.

5 Comments

This seems possible for a small text but when handling a lot of texts, this seems a long detour to come to the solution. What I'm looking for is something like the folowing in python: sorted_list = sorted(Unsorted_list, key=lambda (v, k): [alphabet.index(c) for c in v])
I agree - it is not a particularly elegant solution.
Compile yourself PHP 6, it has that build in.
@hakre can you post the link to this php native function documentation?
@Vinicius.Silva Don't remember it specifically, maybe strtr is it? php.net/strtr - The analogy to PHP 6 must have been a joke, there was never a release of it.
0

Fortunately, your custom alphabet does not have more characters than the list of single-byte latin letters, so translating is a very simple and readable process.

I recommend that you set up a translation array before you begin sorting, then translate/normalize the keys for the purpose of sorting.

Code: (Demo)

$array = [
    '=k_0' => ['test1'],
    'aA_2' => ['test2'],
    'sqA_1' => ['test3'],
    '=kj_0' => ['test4'],
    'awA_2' => ['test5'],
    '= D_1' => ['test6'],
    'sq A_1' => ['test7'],
    'sqA_2' => ['test8'],
];

$trans = ['AjawbpfmnrhHxXsSqkgtTdD =', 'abcdefghijklmnopqrstuvwxy'];

uksort(
    $array,
    function ($a, $b) use ($trans) {
        return strtr($a, ...$trans) <=> strtr($b, ...$trans);
    }
);
var_export($array);

Output:

array (
  'aA_2' => 
  array (
    0 => 'test2',
  ),
  'awA_2' => 
  array (
    0 => 'test5',
  ),
  'sqA_1' => 
  array (
    0 => 'test3',
  ),
  'sqA_2' => 
  array (
    0 => 'test8',
  ),
  'sq A_1' => 
  array (
    0 => 'test7',
  ),
  '=k_0' => 
  array (
    0 => 'test1',
  ),
  '=kj_0' => 
  array (
    0 => 'test4',
  ),
  '= D_1' => 
  array (
    0 => 'test6',
  ),
)

From PHP7.4, the syntax can be reduced using arrow function syntax.

uksort(
    $array,
    fn($a, $b) => strtr($a, ...$trans) <=> strtr($b, ...$trans)
);

1 Comment

@hakre here it goes ^
0

After feedback from @mickmackusa I have updated my example to work with uksrot and answer the question fully

$order = str_split("AjawbpfmnrhHxXsSqkgtTdD");

uksort($arr, function ($a, $b) use ($order) {
    $posA = array_search($a, $order);
    $posB = array_search($b, $order);
    return $posA - $posB;
});

http://sandbox.onlinephpfunctions.com/code/9b6f39b30dcc932517bbe82608dd8a0c8d35b3da

-- original response with usort--

You can use usort() with a custom order array like so

$arr = array("w","b","m","n","x","x","z","T","T","A","A");

$order = array("A","j","a","w","b","p","f","m","n","r","h","H","x","X","s","S","q","k","g","t","T","d","D"," ","=");
    usort($arr, function ($a, $b) use ($order) {
        $posA = array_search($a, $order);
        $posB = array_search($b, $order);
        return $posA - $posB;
    });

(you could probably just explode the $order string so it's nicer)

I actually just came across this answer which explains it better, and handles if a value is not inside the order array.

And a working example http://sandbox.onlinephpfunctions.com/code/3934aafe93377ec18549d326d6551608436242a7

5 Comments

I don't think this technique works as required. Please prove that it works by providing an online demo.
@updated with example. I am no longer using uksort and using usort as originally intended
The OP doesn't want to sort by values. The core problem with your demo/answer is that you are ignoring the OP's requirements and sample data. This answer is incorrect.
Updated now to work with the answer with example
Your snippet is NOT using the OP's very clearly provided multi-character string keys. This answer does not respect the complexity of comparing keys which are longer than one character. If you are confused, read my newly posted and correct answer which respects the complexity of the OP's input data.
-2
<?php
$arr = [8,10,12,18,20,7,4,6,2,20,0]; //take array

 $a= sortasc($arr); // call function

function sortasc($arr){


    for($i=0;$i<=count($arr);$i++){
            for($j=1;$j<=count($arr)-1;$j++){

                         if($arr[$j-1]>$arr[$j]){

                        $temp = $arr[$j];
                        $arr[$j]= $arr[$j-1];
                        $arr[$j-1] = $temp;
                    }
        }
    }
        return $arr;
}

?>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.