note 107087 modified in function.usort by danbrown
| From: | danbrown@php.net | Date: | Fri, 06 Jan 2012 19:13:05 +0000 |
| Subject: | note 107087 modified in function.usort by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-185406@lists.php.net to get a copy of this message | ||
This one may approve multisort performance dramatically.
I had a 100K-row-array with assoc keys and sub arrays, several MBs. Using usort hammered my dev box
cpu for several minutes until I killed it.
My own assoc-version of [someone else's code] did the same. Following Array-Indexing and
sorting solution only took very few secs:
<?php
define('funcname',0);
define('indexfieldinfuncparamspos',1);
define('funcparams',2);
function array_index($dataarr,$field2funcarr){
$indexarr=array();
foreach($dataarr as $key=>$valarr) {
$currentindex='';
foreach($field2funcarr as $fieldid=>$funcarr) if(is_array($funcarr)) {
$funcarr[funcparams][$funcarr[indexfieldinfuncparamspos]]= $valarr[$fieldid];
$currentindex.= call_user_func_array($funcarr[funcname],$funcarr[funcparams]).'_';
} else $currentindex.= $valarr[$fieldid].'_';
$indexarr[$currentindex]=$key;
}
return $indexarr;
}
function array_sortbyindex(&$dataarr,$indexarr,$issortindexbykey=true){
// assumes complete index!: each item of indexarr must correlate a key of dataarr
$resultarr=array();
if($issortindexbykey) ksort($indexarr);
foreach($indexarr as $datakey) $resultarr[$datakey]= $dataarr[$datakey];
return $resultarr;
}
$dataarr=array(
'Franz'=>array('letters'=>5,'wordtype'=>'name'),
'goes'=>array('letters'=>4,'wordtype'=>'verb'),
'to'=>array('letters'=>2,'wordtype'=>'prep'),
'China'=>array('letters'=>5,'wordtype'=>'noun'));
// just build an index for interest (empty string for wordtype as no modification required):
print_r(array_index($dataarr,
array('letters'=>array('str_pad',0,array('',7,'0',STR_PAD_LEFT)),
'wordtype'=>'')));
// build index and sort - all in one go:
print_r(array_sortbyindex($dataarr, array_index($dataarr,
array('letters'=>array('str_pad',0,
array('',7,'0',STR_PAD_LEFT)), 'wordtype'=>''))));
?>
first print_r returns:
Array
(
[0000005_name_] => Franz
[0000004_verb_] => goes
[0000002_prep_] => to
[0000005_noun_] => China
)
second print_r returns:
Array
(
[to] => Array
(
[letters] => 2
[wordtype] => prep
)
[goes] => Array
(
[letters] => 4
[wordtype] => verb
)
[Franz] => Array
(
[letters] => 5
[wordtype] => name
)
[China] => Array
(
[letters] => 5
[wordtype] => noun
)
)
Major Benefits:
- extremly fast
- each sort field can apply an own modifier. Ideally you can use out-of-the-box functions, which
reduces effort for programming callbacks
- you could use the index eg. for sorted data output without physically sorting the data
--was--
This one may approve multisort performance dramatically.
I had a 100K-row-array with assoc keys and sub arrays, several MBs. Using usort hammered my dev box
cpu for several minutes until I killed it.
My own assoc-version of Sreid's mergesort did the same. Following Array-Indexing and sorting
solution only took very few secs:
define('funcname',0);
define('indexfieldinfuncparamspos',1);
define('funcparams',2);
function array_index($dataarr,$field2funcarr){
$indexarr=array();
foreach($dataarr as $key=>$valarr) {
$currentindex='';
foreach($field2funcarr as $fieldid=>$funcarr) if(is_array($funcarr)) {
$funcarr[funcparams][$funcarr[indexfieldinfuncparamspos]]= $valarr[$fieldid];
$currentindex.= call_user_func_array($funcarr[funcname],$funcarr[funcparams]).'_';
} else $currentindex.= $valarr[$fieldid].'_';
$indexarr[$currentindex]=$key;
}
return $indexarr;
}
function array_sortbyindex(&$dataarr,$indexarr,$issortindexbykey=true){
// assumes complete index!: each item of indexarr must correlate a key of dataarr
$resultarr=array();
if($issortindexbykey) ksort($indexarr);
foreach($indexarr as $datakey) $resultarr[$datakey]= $dataarr[$datakey];
return $resultarr;
}
$dataarr=array(
'Franz'=>array('letters'=>5,'wordtype'=>'name'),
'goes'=>array('letters'=>4,'wordtype'=>'verb'),
'to'=>array('letters'=>2,'wordtype'=>'prep'),
'China'=>array('letters'=>5,'wordtype'=>'noun'));
// just build an index for interest (empty string for wordtype as no modification required):
print_r(array_index($dataarr,
array('letters'=>array('str_pad',0,array('',7,'0',STR_PAD_LEFT)),
'wordtype'=>'')));
// build index and sort - all in one go:
print_r(array_sortbyindex($dataarr, array_index($dataarr,
array('letters'=>array('str_pad',0,
array('',7,'0',STR_PAD_LEFT)), 'wordtype'=>''))));
first print_r returns:
Array
(
[0000005_name_] => Franz
[0000004_verb_] => goes
[0000002_prep_] => to
[0000005_noun_] => China
)
second print_r returns:
Array
(
[to] => Array
(
[letters] => 2
[wordtype] => prep
)
[goes] => Array
(
[letters] => 4
[wordtype] => verb
)
[Franz] => Array
(
[letters] => 5
[wordtype] => name
)
[China] => Array
(
[letters] => 5
[wordtype] => noun
)
)
Major Benefits:
- extremly fast
- each sort field can apply an own modifier. Ideally you can use out-of-the-box functions, which
reduces effort for programming callbacks
- you could use the index eg. for sorted data output without physically sorting the data
http://php.net/manual/en/function.usort.php