0

In python, I have the following which works perfectly well:

list = [('wr', ['A1']), ('wr-qA', ['A3']), ('wr,w', ['A4']), ('wr-mw', ['A2']), ('wrs', ['A6']), ('wrD', ['A8']), ('wrS', ['A7']), ('wr.w', ['A5']), ('=k', ['A10']), ('Dd', ['A9'])]

alphabet = " -,.AjawbpfmnrhHxXsSqkgtTdD=/()[]<>{}'*#I1234567890&@"

Sorted_list = sorted(list, key=lambda (v, k): [alphabet.index(c) for c in v])
print Sorted_list

Output:

[('wr', ['A1']), ('wr-mw', ['A2']), ('wr-qA', ['A3']), ('wr,w', ['A4']), ('wr.w', ['A5']), ('wrs', ['A6']), ('wrS', ['A7']), ('wrD', ['A8']), ('Dd', ['A9']), ('=k', ['A10'])]

How can I do the same in PHP with:

$list = array(
    'wr' => 'A1',
    'wr-qA' => 'A3',
    'wr,w' => 'A4',
    'wr-mw' => 'A2',
    'wrs' => 'A6',
    'wrD' => 'A8',
    'wrS' => 'A7',
    'wr.w' => 'A5',
    '=k' => 'A10',
    'Dd' => 'A9'
);
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Preys
  • 121
  • 2
  • 6
  • What is the array in PHP for? – Dhaivat Pandya Jun 16 '11 at 09:40
  • the string used as keys are transcriptions of words in a different writing. Sorting them according to the given alphabet gives you a dictionnary. – Preys Jun 16 '11 at 09:49
  • You are also using a list of tuples in python, but a hash in PHP? Is this intended? – Yet Another Geek Jun 16 '11 at 09:51
  • Please link the original question that belongs to it. – hakre Jun 16 '11 at 09:52
  • @Yet Another Geek Probably not. He doesn't seem to know PHP too well. – Alin Purcaru Jun 16 '11 at 09:55
  • A text looks like this: A1 dwA nTr wr A2 mdw wr-mw A3 wr mrj wr-qA (and so on). The program identifies A1, A2 etc as a reference to the line in the text and makes an array of each word with the reference. In the case of the text above wr has two occurences (in A1 and in A2) so it would be wr => A1, A2; after going through the text I have an multidimensional array composed of arrays My_word => My_references. In this multidim. array I want to sort the arrays alphabeticly based on their key (i.e. My_word) – Preys Jun 16 '11 at 11:22

4 Answers4

4

I don't fully understand your question, but if you need to do custom sorting in PHP you need to use usort or uasort. Probably the second one, as I see you have custom key in your array.

If you're lucky enough and can use PHP 5.3 than you may supply the callback as a closure.

This will be the equivalent in PHP of user sorting. The equivalent of indexOf in PHP would be strpos.

Warning: Take care when comparing the return values of strpos because it may return false if it doesn't find any match. And in PHP false is equal (==) to 0.


About your list structure in PHP. Maybe you need something like this.

$list = array(array('wr', array('A1')), array('wr-qA',array('A3')), ...);

Not sure though.

Alin Purcaru
  • 43,655
  • 12
  • 77
  • 90
  • OH MY GOD. PHP finally got closures. Ahead of Java, so, second-last, that's an achievement, right? – Dhaivat Pandya Jun 16 '11 at 09:51
  • @Dhaivat Java did not need closures as much as PHP, because of anonymous class declarations, so it is purely syntax. In PHP you had to refer to a function by its name in a string, in which closures is a big step forward. – Yet Another Geek Jun 16 '11 at 10:02
  • why are you creating array('A1') and so forth, shoul'nt array('wr', 'A1') be enough? – Yet Another Geek Jun 16 '11 at 10:04
  • @Yet Another Geek What I wrote is just a transliteration of his python code. Wether it should be enclosed in an array or be a simple string, or any other format for that matter, is entirely his decision. – Alin Purcaru Jun 16 '11 at 10:48
1

For the lambda sorting, you can use usort(...) (and strcmp() for comparison)

usort($list, "strcmp"); // PHP function name as a string

Since PHP 5.3 you can also use an anonymous function as a callback parameter

usort($list, function($a, $b) { return strcmp($a, $b) }); 
// Note - callback function must return integer comparison between 2 elements

However, if are sorting by value, you can simply use sort() or if you sort by key, use ksort() (Note that they sort in place and return only a boolean flag)

mkilmanas
  • 3,395
  • 17
  • 27
0

This is what I came up with. It uses uksort(), which takes a user-defined sorting function and sorts the elements based on their keys (which is what you need as it seems).

The code might need a little tweaking, but I tried it and it works. After calling uksort(), the $list variable will contain the sorted array.

In this code example, I used an Anonymous function as a sorting function, which is available from PHP 5.3, before that, you can use a simple function (for examples, you can check the uksort() reference I linked earlier).

$list = array('wr' => 'A1', 'wr-qA' => 'A3', 'wr,w' => 'A4', 'wr-mw' => 'A2', 'wrs' => 'A6', 'wrD' => 'A8', 'wrS' => 'A7', 'wr.w' => 'A5', '=k' => 'A10', 'Dd' => 'A9');
$alphabet = " -,.AjawbpfmnrhHxXsSqkgtTdD=/()[]<>{}'*#I1234567890&@";

uksort($list, function ($a, $b) use ($alphabet) {
    $shorter=min($a, $b);
    $len=strlen($shorter);
    for ($i=0, $len=strlen($shorter); $i < $len; $i++) {
        $aval=strpos($alphabet, $a[$i]);
        $bval=strpos($alphabet, $b[$i]);
        if ($aval!=$bval) {
            return $aval > $bval ? 1 : -1;
        }
    }
    return $shorter==$b ? 1 : -1;
});

EDIT: I quickly wrote a version without an anonymous function:

$list = array('wr' => 'A1', 'wr-qA' => 'A3', 'wr,w' => 'A4', 'wr-mw' => 'A2', 'wrs' => 'A6', 'wrD' => 'A8', 'wrS' => 'A7', 'wr.w' => 'A5', '=k' => 'A10', 'Dd' => 'A9');

function alphabet_sorter($a, $b) {
    $alphabet = " -,.AjawbpfmnrhHxXsSqkgtTdD=/()[]<>{}'*#I1234567890&@";

    $shorter=min($a, $b);
    $len=strlen($shorter);
    for ($i=0, $len=strlen($shorter); $i < $len; $i++) {
        $aval=strpos($alphabet, $a[$i]);
        $bval=strpos($alphabet, $b[$i]);
        if ($aval!=$bval) {
            return $aval > $bval ? 1 : -1;
        }
    }
    return $shorter==$b ? 1 : -1;
}

uksort($list, 'alphabet_sorter');
kapa
  • 77,694
  • 21
  • 158
  • 175
  • I have a problem with the 'use ($alphabet)'. Is this because of my version of php? – Preys Jun 16 '11 at 11:23
  • @Preys Works fine for me. What is your PHP version? If it is at least 5.3, you should show the code somehow that you're using before calling the uksort (maybe use http://pastebin.com/ ). – kapa Jun 16 '11 at 11:25
  • @Preys That won't support anonymous functions. I will quickly rewrite this for you. – kapa Jun 16 '11 at 14:30
0

Using the exact same uksort() function as my answer to your earlier question, you only need to extend the translation string to use upper and lower case letter for non-space letters in your custom alphabet. I withdrew the space from both translation strings because they would both be in the first position and the translation is pointless.

Code: (Demo)

$trans = [
    "-,.AjawbpfmnrhHxXsSqkgtTdD=/()[]<>{}'*#I1234567890&@",
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
];

$list = [
    'wr' => 'A1',
    'wr-qA' => 'A3',
    'wr,w' => 'A4',
    'wr-mw' => 'A2',
    'wrs' => 'A6',
    'wrD' => 'A8',
    'wrS' => 'A7',
    'wr.w' => 'A5',
    '=k' => 'A10',
    'Dd' => 'A9'
];

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

var_export($list);

Output:

array (
  'wr' => 'A1',
  'wr-mw' => 'A2',
  'wr-qA' => 'A3',
  'wr,w' => 'A4',
  'wr.w' => 'A5',
  'wrs' => 'A6',
  'wrS' => 'A7',
  'wrD' => 'A8',
  'Dd' => 'A9',
  '=k' => 'A10',
)
mickmackusa
  • 43,625
  • 12
  • 83
  • 136