$w ) { $sum += $w; # Do not return keys if they have 0 weight. # Note that the "all 0 weight" case is handed above if ( $w > 0 && $sum >= $rand ) { break; } } return $i; } /** * Do a binary search, and return the index of the largest item that sorts * less than or equal to the target value. * * @since 1.23 * * @param callable $valueCallback A function to call to get the value with * a given array index. * @param int $valueCount The number of items accessible via $valueCallback, * indexed from 0 to $valueCount - 1 * @param callable $comparisonCallback A callback to compare two values, returning * -1, 0 or 1 in the style of strcmp(). * @param string $target The target value to find. * * @return int|bool The item index of the lower bound, or false if the target value * sorts before all items. */ public static function findLowerBound( $valueCallback, $valueCount, $comparisonCallback, $target ) { if ( $valueCount === 0 ) { return false; } $min = 0; $max = $valueCount; do { $mid = $min + ( ( $max - $min ) >> 1 ); $item = call_user_func( $valueCallback, $mid ); $comparison = call_user_func( $comparisonCallback, $target, $item ); if ( $comparison > 0 ) { $min = $mid; } elseif ( $comparison == 0 ) { $min = $mid; break; } else { $max = $mid; } } while ( $min < $max - 1 ); if ( $min == 0 ) { $item = call_user_func( $valueCallback, $min ); $comparison = call_user_func( $comparisonCallback, $target, $item ); if ( $comparison < 0 ) { // Before the first item return false; } } return $min; } /** * Do array_diff_assoc() on multi-dimensional arrays. * * Note: empty arrays are removed. * * @since 1.23 * * @param array $array1 The array to compare from * @param array $array2,... More arrays to compare against * @return array An array containing all the values from array1 * that are not present in any of the other arrays. */ public static function arrayDiffAssocRecursive( $array1 ) { $arrays = func_get_args(); array_shift( $arrays ); $ret = []; foreach ( $array1 as $key => $value ) { if ( is_array( $value ) ) { $args = [ $value ]; foreach ( $arrays as $array ) { if ( isset( $array[$key] ) ) { $args[] = $array[$key]; } } $valueret = call_user_func_array( __METHOD__, $args ); if ( count( $valueret ) ) { $ret[$key] = $valueret; } } else { foreach ( $arrays as $array ) { if ( isset( $array[$key] ) && $array[$key] === $value ) { continue 2; } } $ret[$key] = $value; } } return $ret; } }