note 107087 modified in function.usort by danbrown

From: 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

« previous php.notes (#185406) next »