1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Utils;
9:
10: use Nette;
11:
12:
13: 14: 15:
16: class Arrays
17: {
18: use Nette\StaticClass;
19:
20: 21: 22: 23: 24: 25: 26: 27:
28: public static function get(array $arr, $key, $default = null)
29: {
30: foreach (is_array($key) ? $key : [$key] as $k) {
31: if (is_array($arr) && array_key_exists($k, $arr)) {
32: $arr = $arr[$k];
33: } else {
34: if (func_num_args() < 3) {
35: throw new Nette\InvalidArgumentException("Missing item '$k'.");
36: }
37: return $default;
38: }
39: }
40: return $arr;
41: }
42:
43:
44: 45: 46: 47: 48: 49: 50:
51: public static function &getRef(array &$arr, $key)
52: {
53: foreach (is_array($key) ? $key : [$key] as $k) {
54: if (is_array($arr) || $arr === null) {
55: $arr = &$arr[$k];
56: } else {
57: throw new Nette\InvalidArgumentException('Traversed item is not an array.');
58: }
59: }
60: return $arr;
61: }
62:
63:
64: 65: 66: 67:
68: public static function mergeTree(array $arr1, array $arr2)
69: {
70: $res = $arr1 + $arr2;
71: foreach (array_intersect_key($arr1, $arr2) as $k => $v) {
72: if (is_array($v) && is_array($arr2[$k])) {
73: $res[$k] = self::mergeTree($v, $arr2[$k]);
74: }
75: }
76: return $res;
77: }
78:
79:
80: 81: 82: 83:
84: public static function searchKey(array $arr, $key)
85: {
86: $foo = [$key => null];
87: return array_search(key($foo), array_keys($arr), true);
88: }
89:
90:
91: 92: 93: 94:
95: public static function insertBefore(array &$arr, $key, array $inserted)
96: {
97: $offset = (int) self::searchKey($arr, $key);
98: $arr = array_slice($arr, 0, $offset, true) + $inserted + array_slice($arr, $offset, count($arr), true);
99: }
100:
101:
102: 103: 104: 105:
106: public static function insertAfter(array &$arr, $key, array $inserted)
107: {
108: $offset = self::searchKey($arr, $key);
109: $offset = $offset === false ? count($arr) : $offset + 1;
110: $arr = array_slice($arr, 0, $offset, true) + $inserted + array_slice($arr, $offset, count($arr), true);
111: }
112:
113:
114: 115: 116: 117:
118: public static function renameKey(array &$arr, $oldKey, $newKey)
119: {
120: $offset = self::searchKey($arr, $oldKey);
121: if ($offset !== false) {
122: $keys = array_keys($arr);
123: $keys[$offset] = $newKey;
124: $arr = array_combine($keys, $arr);
125: }
126: }
127:
128:
129: 130: 131: 132:
133: public static function grep(array $arr, $pattern, $flags = 0)
134: {
135: return Strings::pcre('preg_grep', [$pattern, $arr, $flags]);
136: }
137:
138:
139: 140: 141: 142:
143: public static function flatten(array $arr, $preserveKeys = false)
144: {
145: $res = [];
146: $cb = $preserveKeys
147: ? function ($v, $k) use (&$res) { $res[$k] = $v; }
148: : function ($v) use (&$res) { $res[] = $v; };
149: array_walk_recursive($arr, $cb);
150: return $res;
151: }
152:
153:
154: 155: 156: 157:
158: public static function isList($value)
159: {
160: return is_array($value) && (!$value || array_keys($value) === range(0, count($value) - 1));
161: }
162:
163:
164: 165: 166: 167:
168: public static function associate(array $arr, $path)
169: {
170: $parts = is_array($path)
171: ? $path
172: : preg_split('#(\[\]|->|=|\|)#', $path, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
173:
174: if (!$parts || $parts[0] === '=' || $parts[0] === '|' || $parts === ['->']) {
175: throw new Nette\InvalidArgumentException("Invalid path '$path'.");
176: }
177:
178: $res = $parts[0] === '->' ? new \stdClass : [];
179:
180: foreach ($arr as $rowOrig) {
181: $row = (array) $rowOrig;
182: $x = &$res;
183:
184: for ($i = 0; $i < count($parts); $i++) {
185: $part = $parts[$i];
186: if ($part === '[]') {
187: $x = &$x[];
188:
189: } elseif ($part === '=') {
190: if (isset($parts[++$i])) {
191: $x = $row[$parts[$i]];
192: $row = null;
193: }
194:
195: } elseif ($part === '->') {
196: if (isset($parts[++$i])) {
197: $x = &$x->{$row[$parts[$i]]};
198: } else {
199: $row = is_object($rowOrig) ? $rowOrig : (object) $row;
200: }
201:
202: } elseif ($part !== '|') {
203: $x = &$x[(string) $row[$part]];
204: }
205: }
206:
207: if ($x === null) {
208: $x = $row;
209: }
210: }
211:
212: return $res;
213: }
214:
215:
216: 217: 218: 219:
220: public static function normalize(array $arr, $filling = null)
221: {
222: $res = [];
223: foreach ($arr as $k => $v) {
224: $res[is_int($k) ? $v : $k] = is_int($k) ? $filling : $v;
225: }
226: return $res;
227: }
228:
229:
230: 231: 232: 233: 234: 235: 236: 237:
238: public static function pick(array &$arr, $key, $default = null)
239: {
240: if (array_key_exists($key, $arr)) {
241: $value = $arr[$key];
242: unset($arr[$key]);
243: return $value;
244:
245: } elseif (func_num_args() < 3) {
246: throw new Nette\InvalidArgumentException("Missing item '$key'.");
247:
248: } else {
249: return $default;
250: }
251: }
252:
253:
254: 255: 256: 257:
258: public static function some(array $arr, callable $callback)
259: {
260: foreach ($arr as $k => $v) {
261: if ($callback($v, $k, $arr)) {
262: return true;
263: }
264: }
265: return false;
266: }
267:
268:
269: 270: 271: 272:
273: public static function every(array $arr, callable $callback)
274: {
275: foreach ($arr as $k => $v) {
276: if (!$callback($v, $k, $arr)) {
277: return false;
278: }
279: }
280: return true;
281: }
282:
283:
284: 285: 286: 287:
288: public static function map(array $arr, callable $callback)
289: {
290: $res = [];
291: foreach ($arr as $k => $v) {
292: $res[$k] = $callback($v, $k, $arr);
293: }
294: return $res;
295: }
296: }
297: