note 24040 added to function.array-search

From: Date: Mon, 05 Aug 2002 04:52:53 +0000
Subject: note 24040 added to function.array-search
Groups: php.notes 
Request: Send a blank email to php-notes+get-34283@lists.php.net to get a copy of this message
The following function I created should have 15 lines of code from the first if to the last return (lines 1-2,6,8-12 start with if). Csaba Gabor function InsertPt ($ar, $val, $searchType=0, $startPos=0, $endPos=null) { // Finds the position where $val should be array_spliced into // subarray $ar[$startPos ... $endPos] to maintain the // sortedness of $ar (which entire array is assumed either // ascending or descending). // This position is unique unless $val equals an $ar element: // // In this case the insertion point is such that // insertion of $val would happen between the first // encountered $val in the subarray and the element // just prior to that, where the search is STARTING from // the smallest (!$searchType is true) or // largest (!!$searchType is true) side of the array // // $startPos, $endPos are restricted to // [-sizeof($ar),sizeof($ar)-1] and are interchangeable // UNLESS all elements are identical in which case it // establishes the ascending order. If $ar is a singleton, // it is assumed ascending. // $endPos defaults to the end of the array // (0 if $startPos is negative, and // [the normal case] sizeof($ar)-1 otherwise). // Negative position values should be subtracted from // sizeof($ar) to get absolute position. // Logarithmic speed. Works with strings. // Adaptable to case insensitive strings (7 comparisons) // Examples with $ar = array(2, 4, 5, 5, 5, 6, 7, 10, 12) // InsertPt ($ar, 8) => 7 // InsertPt ($ar, 5) => 2 before first 5 // InsertPt ($ar, 5, 1) => 5 after the last 5 // InsertPt ($ar, -3) => 0 before the 2 // InsertPt ($ar, 12, 1) => 9 after the 12 // If $ar was reversed, the same five // functions calls would produce 2, 7, 4, 9, 0 // If $ar = [6, 6, 6, 6, 6] // InsertPt ($ar, 8) => 5 // InsertPt ($ar, 6, 1, -1, 2) => 2 // that -1 translates to 4, which implies descending order if (!$ar || $startPos<-($aSize=sizeof($ar)) || $startPos>$aSize-1) return 0; if ($endPos===null) $endPos = 0 - ($startPos>=0); // default $endPos adjustment $startPos = mod(min($aSize-1, (max (-$aSize, $startPos))),$aSize); // translate to real start pos $endPos = mod(min($aSize-1, (max (-$aSize, $endPos))), $aSize); // translate to real end pos $diff = $endPos-$startPos; if (!($dir = ($ar[0]==$ar[$aSize-1] ? 0 : ($ar[$aSize-1]<$ar[0] ? 1 : -1)))) // constant series (-1 for ascending, 1 for descending) return (($val<$ar[0] || ($val==$ar[0] && !$searchType)) ? $startPos + ($diff<0) : $endPos + !($diff<0)); if ($diff<0) { $startPos+=$endPos; $endPos=$startPos-$endPos; $startPos-=$endPos; } // make sure $startPos <= $endPos if ($val<$ar[($dir<0 ? $startPos : $endPos)]) return ($dir<0 ? $startPos : $endPos+1); // These 2 lines for when $val falls outside if ($val>$ar[($dir<0 ? $endPos : $startPos)]) return ($dir<0 ? $endPos+1 : $startPos); // series speced by $startPos, $endPos if ($val==$ar[($tmp=(($dir<0)==!$searchType)) ? $startPos : $endPos]) return ($tmp ? $startPos : $endPos+1); // if $val at sensitive endpoint if (abs($diff)==1) return $endPos; // Double series (singleton was covered in 3 prior lines) $mid = floor(($endPos+$startPos)/2); // We will halve the series $tmp = ($dir<0)==(($val==$ar[$mid]) ? !$searchType : ($val<$ar[$mid])); // Decide which half we want return InsertPt ($ar, $val, $searchType, $tmp ? $startPos : $mid, $tmp ? $mid : $endPos); } function mod($num, $base) { // returns $num modulo $base within range [0..$base-1] return ($num - $base*floor($num/$base)); } -- http://www.php.net/manual/en/function.array-search.php http://master.php.net/manage/user-notes.php?action=edit+24040 http://master.php.net/manage/user-notes.php?action=delete+24040 http://master.php.net/manage/user-notes.php?action=reject+24040

« previous php.notes (#34283) next »