function mergesort($data) { // Only process if we're not down to one piece of data if (count($data) > 1) { // Find out the middle of the current data set and split it there to obtain to halfs $data_middle = round(count($data) / 2, 0, PHP_ROUND_HALF_DOWN); // and now for some recursive magic $data_part1 = mergesort(array_slice($data, 0, $data_middle)); $data_part2 = mergesort(array_slice($data, $data_middle, count($data))); // Setup counters so we can remember which piece of data in each half we're looking at $counter1 = $counter2 = 0; // iterate over all pieces of the currently processed array, compare size & reassemble for ($i = 0; $i < count($data); $i++) { // if we're done processing one half, take the rest from the 2nd half if ($counter1 == count($data_part1)) { $data[$i] = $data_part2[$counter2]; ++$counter2; // if we're done with the 2nd half as well or as long as pieces in the first half are still smaller than the 2nd half } elseif ($counter2 == count($data_part2) or $data_part1[$counter1] < $data_part2[$counter2]) { $data[$i] = $data_part1[$counter1]; ++$counter1; } else { $data[$i] = $data_part2[$counter2]; ++$counter2; } } } return $data; }
function mergesort(&$shulie, $start, $end) { if ($start < $end) { $middle = floor(($start + $end) / 2); mergesort($shulie, $start, $middle); mergesort($shulie, $middle + 1, $end); merge($shulie, $start, $middle, $end); } }
function mergesort(&$lst, $a, $b) { if ($b - $a < 2) { return; } $half = floor(($b + $a) / 2); mergesort($lst, $a, $half); mergesort($lst, $half, $b); merge($lst, $a, $half, $b); }
function mergesort($arr) { if (count($arr) == 1) { return $arr; } $mid = count($arr) / 2; $left = array_slice($arr, 0, $mid); $right = array_slice($arr, $mid); $left = mergesort($left); $right = mergesort($right); return merge($left, $right); }
function mergesort(&$a) { $cnt = count($a); if ($cnt <= 1) { return $a; } $half = $cnt / 2; if ($cnt % 2 != 0) { $half -= 0.5; } $a1 = array_slice($a, 0, $half); $a2 = array_slice($a, $half, $cnt - $half); mergesort($a1); mergesort($a2); $a = merge($a1, $a2); }
/** * Sort array but maintain index when compared items are equal. * http://www.php.net/manual/en/function.usort.php#38827 * * @param array &$array input array * @param callable $cmp_function custom function to compare values * * @return void * */ function mergesort(&$array, $cmp_function) { // Arrays of size < 2 require no action. if (count($array) < 2) { return; } // Split the array in half $halfway = count($array) / 2; $array1 = array_slice($array, 0, $halfway); $array2 = array_slice($array, $halfway); // Recurse to sort the two halves mergesort($array1, $cmp_function); mergesort($array2, $cmp_function); // If all of $array1 is <= all of $array2, just append them. if (call_user_func($cmp_function, end($array1), $array2[0]) < 1) { $array = array_merge($array1, $array2); return; } // Merge the two sorted arrays into a single sorted array $array = array(); $ptr1 = $ptr2 = 0; while ($ptr1 < count($array1) && $ptr2 < count($array2)) { if (call_user_func($cmp_function, $array1[$ptr1], $array2[$ptr2]) < 1) { $array[] = $array1[$ptr1++]; } else { $array[] = $array2[$ptr2++]; } } // Merge the remainder while ($ptr1 < count($array1)) { $array[] = $array1[$ptr1++]; } while ($ptr2 < count($array2)) { $array[] = $array2[$ptr2++]; } return; }
/** * HTTP Content Negotiation * * Using the content negotiation algorithm specified in * {@link http://cidr-report.org/ietf/all-ids/draft-ietf-http-v11-spec-00.txt draft-ietf-http-v11-spec-00}, * will return the most appropriate variants (may be more then one that * works) based on the provided request headers. This function is based * off of {@link http://search.cpan.org/dist/libwww-perl/lib/HTTP/Negotiate.pm libwww-perl, HTTP::Negotiate, choose()}. * * Usage: * <code> * $variants = array( * array( * id => 'var1', * qs => 1.000, * type => 'text/html', * encoding => null, * charset => 'iso-8859-1', * language => 'en', * size => 3000 * ), * array( * id => 'var2', * qs => 1.000, * type => 'application/xhtml+xml', * encoding => null, * charset => 'iso-8859-1', * language => 'en', * size => 3000 * ), * ); * * $request_headers = array( * HTTP_ACCEPT => 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,{@*}*;q=0.5', * HTTP_ACCEPT_LANGUAGE => 'en-us,en;q=0.5', * HTTP_ACCEPT_CHARSET => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', * HTTP_ACCEPT_ENCODING => 'gzip,deflate' * ); * * $results = HTTP_Negotiate::choose($variants, $request_headers); * assertTrue(count($results) == 1 && $results[0]['id'] == 'var2'); * </code> * * More information on accept headers can be found at * {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html} * * @access public * @author Gary Court <*****@*****.**> * @param array $variants Array of array of strings which contain the supported parameters of each variant (supported keys: id, qs, type, encoding, charset, language, size) * @param array $request_headers Array of strings which contain the request header (supported keys: HTTP_ACCEPT, HTTP_ACCEPT_LANGUAGE, HTTP_ACCEPT_CHARSET, HTTP_ACCEPT_ENCODING). If null, $_SERVER is used. * @return array The acceptable variants (from $variants) based on the request headers. May return more then one acceptable variant (in original order) or may return null (if no acceptable variant was found). * @static * @version 1.0 * @todo Support for parameters in variant->type. */ function choose($variants, $request_headers = null) { //check arguments if (!is_array($variants)) { return false; } if ($request_headers === null) { $request_headers = $_SERVER; } elseif (!is_array($request_headers)) { return false; } //parse all accept values $request = array(); $request_header_keys = array_keys($request_headers); foreach ($request_header_keys as $request_header_key) { $accept_type = null; if (strpos($request_header_key, 'HTTP_ACCEPT_') !== false) { $accept_type = strtolower(substr($request_header_key, strlen('HTTP_ACCEPT_'))); } elseif ($request_header_key == 'HTTP_ACCEPT') { $accept_type = 'type'; } if ($accept_type) { $request[$accept_type] = array(); $accept_variants = array_trim(explode(',', $request_headers[$request_header_key])); foreach ($accept_variants as $accept_variant) { if ($accept_variant) { $accept_variant_parameters = array_trim(explode(';', $accept_variant)); $request[$accept_type][$accept_variant_parameters[0]] = array(); for ($i = 1; $i < count($accept_variant_parameters); $i++) { if (strpos($accept_variant_parameters[$i], '=') !== false) { $accept_variant_parameter_values = array_trim(explode('=', $accept_variant_parameters[$i])); $accept_variant_parameter_values[1] = convert_type($accept_variant_parameter_values[1]); if ($accept_variant_parameter_values[0] == 'q') { if ($accept_variant_parameter_values[1] > 1.0) { $accept_variant_parameter_values[1] = 1.0; } elseif ($accept_variant_parameter_values[1] < 0.0) { $accept_variant_parameter_values[1] = 0.0; } } if ($accept_variant_parameter_values[0] == 'mxb' && $accept_variant_parameter_values[1] < 0) { $accept_variant_parameter_values[1] = 0; } $request[$accept_type][$accept_variant_parameters[0]][$accept_variant_parameter_values[0]] = $accept_variant_parameter_values[1]; } } if (!isset($request[$accept_type][$accept_variant_parameters[0]]['q'])) { $request[$accept_type][$accept_variant_parameters[0]]['q'] = 1.0; } } } } } //determine if at least one variant specifies a language $language_variant_specified = false; foreach ($variants as $variant) { if (isset($variant['language'])) { $language_variant_specified = true; break; } } //determine the best variant for the request $results = array(); foreach ($variants as $variant) { //calculate qs if (!isset($variant['qs']) || !is_numeric($variant['qs'])) { $qs = 1.0; } else { $qs = (double) convert_type($variant['qs']); } //calculate qe if (!isset($request['encoding'])) { $qe = 1.0; } elseif (!isset($variant['encoding']) || !count($request['encoding'])) { $qe = 1.0; } elseif (array_key_exists($variant['encoding'], $request['encoding'])) { $qe = (double) $request['encoding'][$variant['encoding']]['q']; } elseif ($variant['encoding'] == 'identity') { $qe = 1.0; } elseif (isset($request['encoding']['*'])) { $qe = (double) $request['encoding']['*']['q']; } else { $qe = 0.0; } // --------- // hack by Brian // changed !count(... to !isset($request['charset']) // --------- //calculate qc if (!isset($request['charset'])) { $qc = 1.0; } elseif (!isset($variant['charset']) || $variant['charset'] == 'US-ASCII' || !isset($request['charset'])) { $qc = 1.0; } elseif (array_key_exists($variant['charset'], $request['charset'])) { $qc = (double) $request['charset'][$variant['charset']]['q']; } elseif (isset($request['charset']['*'])) { $qc = (double) $request['charset']['*']['q']; } else { $qc = 0.0; } //calculate ql if (!isset($request['language'])) { $ql = 1.0; } elseif (!$language_variant_specified || !count($request['language'])) { $ql = 1.0; } elseif (!isset($variant['language'])) { $ql = 0.5; } elseif (array_key_exists($variant['language'], $request['language'])) { $ql = (double) $request['language'][$variant['language']]['q']; } elseif (array_key_exists(substr($variant['language'], 0, 2), $request['language'])) { $ql = (double) $request['language'][substr($variant['language'], 0, 2)]['q']; } elseif (isset($request['language']['*'])) { $ql = (double) $request['language']['*']['q']; } else { $ql = 0.001; } //calculate q & mxb $mxb = null; // --------- // hack by Brian below added (6) !(isset... // to prevent warnings on strict php setups // --------- if (!isset($request['type'])) { $q = 0.0; } elseif (!isset($variant['type'])) { $q = 0.0; } elseif (!count($request['type'])) { $q = 1.0; } elseif (array_key_exists($variant['type'], $request['type'])) { if (!isset($request['type'][$variant['type']]['q'])) { $request['type'][$variant['type']]['q'] = $q; } $q = (double) $request['type'][$variant['type']]['q']; if (!isset($request['type'][$variant['type']]['mxb'])) { $request['type'][$variant['type']]['mxb'] = $mxb; } $mxb = $request['type'][$variant['type']]['mxb']; } elseif (array_key_exists(strtok($variant['type'], '/') . '/*', $request['type'])) { if (!isset($request['type'][strtok($variant['type'], '/') . '/*']['q'])) { $request['type'][strtok($variant['type'], '/') . '/*']['q'] = $q; } $q = (double) $request['type'][strtok($variant['type'], '/') . '/*']['q']; if (!isset($request['type'][strtok($variant['type'], '/') . '/*']['mxb'])) { $request['type'][strtok($variant['type'], '/') . '/*']['mxb'] = $mxb; } $mxb = $request['type'][strtok($variant['type'], '/') . '/*']['mxb']; } elseif (array_key_exists('*/*', $request['type'])) { if (!isset($request['type']['*/*']['q'])) { $request['type']['*/*']['q'] = $q; } $q = (double) $request['type']['*/*']['q']; if (!isset($request['type']['*/*']['mxb'])) { $request['type']['*/*']['mxb'] = $mxb; } $mxb = $request['type']['*/*']['mxb']; } else { $q = 0.0; } //calculate bs $bs = $variant['size']; //calculate Q if ($mxb === null || $bs === null || $mxb >= $bs) { $Q = $qs * $qe * $qc * $ql * $q; } else { $Q = 0.0; } //keep track of the highest Q values $variant['Q'] = $Q; if (!count($results) || $variant['Q'] > $results[0]['Q']) { $results = array($variant); } elseif ($variant['Q'] == $results[0]['Q']) { array_push($results, $variant); } } //sort results (which all have same Q) by smallest filesize, ascending if (!function_exists('compareVariants')) { function compareVariants($a, $b) { if ($a['Q'] == $b['Q']) { if (isset($a['size'])) { if (isset($b['size'])) { if ($a['size'] == $b['size']) { return 0; } return $a['size'] < $b['size'] ? -1 : 1; } return -1; } if (isset($b['size'])) { return 1; } return 0; } return $a['Q'] < $b['Q'] ? 1 : -1; } } mergesort($results, 'compareVariants'); //return variants ordered by best choice return $results; }
/** * Render all views for a specific region. * * @param string $region which region to use * * @return $this */ public function render($region = 'main') { if (!isset($this->views[$region])) { return $this; } mergesort($this->views[$region], function ($a, $b) { $sa = $a->sortOrder(); $sb = $b->sortOrder(); if ($sa == $sb) { return 0; } return $sa < $sb ? -1 : 1; }); foreach ($this->views[$region] as $view) { $view->render(); } return $this; }
function sortByGroup() { if (!empty($this->_repositories)) { mergesort($this->_repositories, 'cmpGroups'); } }
function mergesort(&$array, $cmp_function) { //base case, end if (count($array) <= 1) { return; } else { //find middle, get two arrays, recursive call $middle = count($array) / 2; $array1 = array_slice($array, 0, $middle); $array2 = array_slice($array, $middle); mergesort($array1, $cmp_function); mergesort($array2, $cmp_function); //if the arrays are sorted if (call_user_func($cmp_function, end($array1), $array2[0]) < 1) { $array = array_merge($array1, $array2); return; } else { //populate the array $array = array(); $currIndex1 = 0; $currIndex2 = 0; //while both arrays still have values while ($currIndex1 < count($array1) && $currIndex2 < count($array2)) { // call my comparison function to sort them if (call_user_func($cmp_function, $array1[$currIndex1], $array2[$currIndex2]) < 1) { $array[] = $array1[$currIndex1++]; } else { $array[] = $array2[$currIndex2++]; } } // find out which array still has values, and fill the rest in if ($currIndex1 < count($array1)) { while ($currIndex1 < count($array1)) { $array[] = $array1[$currIndex1++]; } } else { while ($currIndex2 < count($array2)) { $array[] = $array2[$currIndex2++]; } } } return; } }
function mergesort(&$array, $sortby) { // Arrays of size < 2 require no action. if (count($array) < 2) return; // Split the array in half $halfway = count($array) / 2; $array1 = array_slice($array, 0, $halfway); $array2 = array_slice($array, $halfway); // Recurse to sort the two halves mergesort($array1, $sortby); mergesort($array2, $sortby); // If all of $array1 is <= all of $array2, just append them. $last = end($array1); if (strnatcasecmp($last->getVarValue($sortby), $array2[0]->getVarValue($sortby)) < 1) { $array = array_merge($array1, $array2); return; } // Merge the two sorted arrays into a single sorted array $array = array(); $ptr1 = $ptr2 = 0; while ($ptr1 < count($array1) && $ptr2 < count($array2)) { if (strnatcasecmp($array1[$ptr1]->getVarValue($sortby), $array2[$ptr2]->getVarValue($sortby)) < 1) $array[] = $array1[$ptr1++]; else $array[] = $array2[$ptr2++]; } // Merge the remainder while ($ptr1 < count($array1)) $array[] = $array1[$ptr1++]; while ($ptr2 < count($array2)) $array[] = $array2[$ptr2++]; }