Tough to explain so here's an example:
$strings = array(
array("languageCode" => "ES", "string" => "hola"),
array("languageCode" => "EN", "string" => "hello"),
array("languageCode" => "IT", "string" => "ciao"),
array("languageCode" => "CHS", "string" => "您好"),
);
I would like to sort strings by languageCode
value, by defining the order:
function magicStringOrder(array $strings, array $languageCodeOrder){
// ....
return $strings;
}
$strings = magicStringOrder($strings, array('EN', 'IT') );
$strings = array(
array("languageCode" => "EN", "string" => "hello"),
array("languageCode" => "IT", "string" => "ciao"),
array("languageCode" => "ES", "string" => "hola"),
array("languageCode" => "CHS", "string" => "您好"),
);
There is magicStringOrder
?
I now know that it is a simple problem to solve with a few loops. I would need a very fast function (it is called many times, with large array)
Another idea without php sort functions:
// sort by cmp $arr[$magic_key] <-> arr $magic_order
function magicSort($arr, $magic_key="", $magic_order = array())
{
$sorted = array();
foreach($magic_order AS $v) {
foreach($arr AS $k2 => $v2) {
if($v===$v2[$magic_key]) {
$sorted[] = $v2;
unset($arr[$k2]);
}
}
}
// attach what's left
return array_merge($sorted, $arr);
}
Test it at eval.in (link expires soon)
$strings = array(
array("languageCode" => "ES", "string" => "hola"),
array("languageCode" => "EN", "string" => "hello"),
array("languageCode" => "IT", "string" => "ciao"),
array("languageCode" => "CHS", "string" => "??"),
);
print_r(magicSort($strings, "languageCode", array("EN", "IT")));
outputs to:
Array
(
[0] => Array
(
[languageCode] => EN
[string] => hello
)
[1] => Array
(
[languageCode] => IT
[string] => ciao
)
[2] => Array
(
[languageCode] => ES
[string] => hola
)
[3] => Array
(
[languageCode] => CHS
[string] => 您好
)
)
$magic_order
can also be empty. If so, the array is just reindexed. Arrays with values, that don't exist in $magic_order
are shifted down and order of those is maintained.
Not sure, if that's exactly what you need.
If it's not a problem to give a weight to a language, the sorting becomes much easier and therefore quicker.
You can use asort
to sort the array based on the $languageCodeOrder
stored weights. If a language it's not present in the $languageCodeOrder
its weight becomes 0 and goes towards the end of the ordered array.
The final order of the array will be from high weight to low. That is: if EN has a weight of 1 it will appear in the array after IT that has 2.
$strings = array(
array("languageCode" => "ES", "string" => "hola"),
array("languageCode" => "EN", "string" => "hello"),
array("languageCode" => "IT", "string" => "ciao"),
array("languageCode" => "CHS", "string" => "您好"),
);
function magicStringOrder(array $strings, array $languageCodeOrder) {
uasort($strings, function($a,$b) use ($languageCodeOrder) {
$val_a = (isset($languageCodeOrder[$a["languageCode"]])) ? $languageCodeOrder[$a["languageCode"]] : 0;
$val_b = (isset($languageCodeOrder[$b["languageCode"]])) ? $languageCodeOrder[$b["languageCode"]] : 0;
return $val_b - $val_a;
});
return $strings;
}
$strings_ordered = magicStringOrder($strings, array('EN' => 1, 'IT' => 2, 'ES' => 3, 'CHS' => 4));
print_r($strings_ordered);
If the arrays are big, it's better to rely on PHP sort algorithms rather than trying to implement custom ones.
Feel free to modify anything in the algorithm (order or whatever).