MediaWiki master
ArrayUtils.php
Go to the documentation of this file.
1<?php
10
37 public static function consistentHashSort( &$array, $key, $separator = "\000" ) {
38 $hashes = [];
39 foreach ( $array as $elt ) {
40 $hashes[$elt] = md5( $elt . $separator . $key );
41 }
42 uasort( $array, static function ( $a, $b ) use ( $hashes ) {
43 return strcmp( $hashes[$a], $hashes[$b] );
44 } );
45 }
46
54 public static function pickRandom( $weights ) {
55 if ( !is_array( $weights ) || count( $weights ) == 0 ) {
56 return false;
57 }
58
59 $sum = array_sum( $weights );
60 if ( $sum == 0 ) {
61 # No loads on any of them
62 # In previous versions, this triggered an unweighted random selection,
63 # but this feature has been removed as of April 2006 to allow for strict
64 # separation of query groups.
65 return false;
66 }
67 $max = mt_getrandmax();
68 $rand = mt_rand( 0, $max ) / $max * $sum;
69
70 $sum = 0;
71 foreach ( $weights as $i => $w ) {
72 $sum += $w;
73 # Do not return keys if they have 0 weight.
74 # Note that the "all 0 weight" case is handed above
75 if ( $w > 0 && $sum >= $rand ) {
76 break;
77 }
78 }
79
80 return $i;
81 }
82
100 public static function findLowerBound( $valueCallback, $valueCount,
101 $comparisonCallback, $target
102 ) {
103 if ( $valueCount === 0 ) {
104 return false;
105 }
106
107 $min = 0;
108 $max = $valueCount;
109 do {
110 $mid = $min + ( ( $max - $min ) >> 1 );
111 $item = $valueCallback( $mid );
112 $comparison = $comparisonCallback( $target, $item );
113 if ( $comparison > 0 ) {
114 $min = $mid;
115 } elseif ( $comparison == 0 ) {
116 $min = $mid;
117 break;
118 } else {
119 $max = $mid;
120 }
121 } while ( $min < $max - 1 );
122
123 if ( $min == 0 ) {
124 $item = $valueCallback( $min );
125 $comparison = $comparisonCallback( $target, $item );
126 if ( $comparison < 0 ) {
127 // Before the first item
128 return false;
129 }
130 }
131 return $min;
132 }
133
146 public static function arrayDiffAssocRecursive( $array1, ...$arrays ) {
147 $ret = [];
148
149 foreach ( $array1 as $key => $value ) {
150 if ( is_array( $value ) ) {
151 $args = [ $value ];
152 foreach ( $arrays as $array ) {
153 if ( isset( $array[$key] ) ) {
154 $args[] = $array[$key];
155 }
156 }
157 $valueret = self::arrayDiffAssocRecursive( ...$args );
158 if ( count( $valueret ) ) {
159 $ret[$key] = $valueret;
160 }
161 } else {
162 foreach ( $arrays as $array ) {
163 if ( isset( $array[$key] ) && $array[$key] === $value ) {
164 continue 2;
165 }
166 }
167 $ret[$key] = $value;
168 }
169 }
170
171 return $ret;
172 }
173
198 public static function cartesianProduct( ...$inputArrays ) {
199 $numInputs = count( $inputArrays );
200 if ( $numInputs === 0 ) {
201 return [];
202 }
203
204 // Reset the internal pointers
205 foreach ( $inputArrays as &$inputArray ) {
206 if ( !count( $inputArray ) ) {
207 return [];
208 }
209 reset( $inputArray );
210 }
211 unset( $inputArray );
212
213 $outputArrays = [];
214 $done = false;
215 while ( !$done ) {
216 // Construct the output array element
217 $element = [];
218 foreach ( $inputArrays as $inputArray ) {
219 $element[] = current( $inputArray );
220 }
221 $outputArrays[] = $element;
222
223 // Increment the pointers starting from the least significant.
224 // If the least significant rolls over back to the start of the
225 // array, continue with the next most significant, and so on until
226 // that stops happening. If all pointers roll over, we are done.
227 $done = true;
228 for ( $paramIndex = $numInputs - 1; $paramIndex >= 0; $paramIndex-- ) {
229 next( $inputArrays[$paramIndex] );
230 if ( key( $inputArrays[$paramIndex] ) === null ) {
231 reset( $inputArrays[$paramIndex] );
232 // continue
233 } else {
234 $done = false;
235 break;
236 }
237 }
238 }
239 return $outputArrays;
240 }
241}
242
244class_alias( ArrayUtils::class, 'ArrayUtils' );
A collection of static methods to play with arrays.
static findLowerBound( $valueCallback, $valueCount, $comparisonCallback, $target)
Do a binary search, and return the index of the largest item that sorts less than or equal to the tar...
static consistentHashSort(&$array, $key, $separator="\000")
Sort the given array in a pseudo-random order which depends only on the given key and each element va...
static pickRandom( $weights)
Given an array of non-normalised probabilities, this function will select an element and return the a...
static cartesianProduct(... $inputArrays)
Make an array consisting of every combination of the elements of the input arrays.
static arrayDiffAssocRecursive( $array1,... $arrays)
Do array_diff_assoc() on multi-dimensional arrays.