MediaWiki master
ArrayUtils.php
Go to the documentation of this file.
1<?php
24
51 public static function consistentHashSort( &$array, $key, $separator = "\000" ) {
52 $hashes = [];
53 foreach ( $array as $elt ) {
54 $hashes[$elt] = md5( $elt . $separator . $key );
55 }
56 uasort( $array, static function ( $a, $b ) use ( $hashes ) {
57 return strcmp( $hashes[$a], $hashes[$b] );
58 } );
59 }
60
68 public static function pickRandom( $weights ) {
69 if ( !is_array( $weights ) || count( $weights ) == 0 ) {
70 return false;
71 }
72
73 $sum = array_sum( $weights );
74 if ( $sum == 0 ) {
75 # No loads on any of them
76 # In previous versions, this triggered an unweighted random selection,
77 # but this feature has been removed as of April 2006 to allow for strict
78 # separation of query groups.
79 return false;
80 }
81 $max = mt_getrandmax();
82 $rand = mt_rand( 0, $max ) / $max * $sum;
83
84 $sum = 0;
85 foreach ( $weights as $i => $w ) {
86 $sum += $w;
87 # Do not return keys if they have 0 weight.
88 # Note that the "all 0 weight" case is handed above
89 if ( $w > 0 && $sum >= $rand ) {
90 break;
91 }
92 }
93
94 return $i;
95 }
96
114 public static function findLowerBound( $valueCallback, $valueCount,
115 $comparisonCallback, $target
116 ) {
117 if ( $valueCount === 0 ) {
118 return false;
119 }
120
121 $min = 0;
122 $max = $valueCount;
123 do {
124 $mid = $min + ( ( $max - $min ) >> 1 );
125 $item = $valueCallback( $mid );
126 $comparison = $comparisonCallback( $target, $item );
127 if ( $comparison > 0 ) {
128 $min = $mid;
129 } elseif ( $comparison == 0 ) {
130 $min = $mid;
131 break;
132 } else {
133 $max = $mid;
134 }
135 } while ( $min < $max - 1 );
136
137 if ( $min == 0 ) {
138 $item = $valueCallback( $min );
139 $comparison = $comparisonCallback( $target, $item );
140 if ( $comparison < 0 ) {
141 // Before the first item
142 return false;
143 }
144 }
145 return $min;
146 }
147
160 public static function arrayDiffAssocRecursive( $array1, ...$arrays ) {
161 $ret = [];
162
163 foreach ( $array1 as $key => $value ) {
164 if ( is_array( $value ) ) {
165 $args = [ $value ];
166 foreach ( $arrays as $array ) {
167 if ( isset( $array[$key] ) ) {
168 $args[] = $array[$key];
169 }
170 }
171 $valueret = self::arrayDiffAssocRecursive( ...$args );
172 if ( count( $valueret ) ) {
173 $ret[$key] = $valueret;
174 }
175 } else {
176 foreach ( $arrays as $array ) {
177 if ( isset( $array[$key] ) && $array[$key] === $value ) {
178 continue 2;
179 }
180 }
181 $ret[$key] = $value;
182 }
183 }
184
185 return $ret;
186 }
187
212 public static function cartesianProduct( ...$inputArrays ) {
213 $numInputs = count( $inputArrays );
214 if ( $numInputs === 0 ) {
215 return [];
216 }
217
218 // Reset the internal pointers
219 foreach ( $inputArrays as &$inputArray ) {
220 if ( !count( $inputArray ) ) {
221 return [];
222 }
223 reset( $inputArray );
224 }
225 unset( $inputArray );
226
227 $outputArrays = [];
228 $done = false;
229 while ( !$done ) {
230 // Construct the output array element
231 $element = [];
232 foreach ( $inputArrays as $inputArray ) {
233 $element[] = current( $inputArray );
234 }
235 $outputArrays[] = $element;
236
237 // Increment the pointers starting from the least significant.
238 // If the least significant rolls over back to the start of the
239 // array, continue with the next most significant, and so on until
240 // that stops happening. If all pointers roll over, we are done.
241 $done = true;
242 for ( $paramIndex = $numInputs - 1; $paramIndex >= 0; $paramIndex-- ) {
243 next( $inputArrays[$paramIndex] );
244 if ( key( $inputArrays[$paramIndex] ) === null ) {
245 reset( $inputArrays[$paramIndex] );
246 // continue
247 } else {
248 $done = false;
249 break;
250 }
251 }
252 }
253 return $outputArrays;
254 }
255}
256
258class_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.