Skip to content

Commit a6f72ed

Browse files
committed
Added each method and updated README links
1 parent db13b33 commit a6f72ed

File tree

5 files changed

+124
-2
lines changed

5 files changed

+124
-2
lines changed

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ Advanced implementation of well known operations:
1313
* [Set](https://minwork.gitbook.io/array/common-methods/set-setnestedelement)
1414
* [Has](https://minwork.gitbook.io/array/common-methods/has)
1515
* [Map](https://minwork.gitbook.io/array/manipulating-array/mapping)
16+
* [Each](https://minwork.gitbook.io/array/traversing-array/iterating)
1617
* [Filter](https://minwork.gitbook.io/array/manipulating-array/filtering)
17-
* [Find](https://minwork.gitbook.io/array/manipulating-array/finding)
18+
* [Find](https://minwork.gitbook.io/array/traversing-array/finding)
1819
* [Group](https://minwork.gitbook.io/array/manipulating-array/grouping)
1920
* [Sort](https://minwork.gitbook.io/array/manipulating-array/sorting)
2021
* [Check](https://minwork.gitbook.io/array/validating-array/check)

src/Arr.php

+67
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,27 @@ class Arr
4747
*/
4848
const MAP_ARRAY_VALUE_KEY = 8;
4949

50+
/**
51+
* Iterate using callback in form of function($value)
52+
*/
53+
const EACH_VALUE = 0;
54+
/**
55+
* Iterate using callback in form of function($key, $value)
56+
*/
57+
const EACH_KEY_VALUE = 1;
58+
/**
59+
* Iterate using callback in form of function($value, $key1, $key2, ...)
60+
*/
61+
const EACH_VALUE_KEYS_LIST = 2;
62+
/**
63+
* Iterate using callback in form of function(array $keys, $value)
64+
*/
65+
const EACH_KEYS_ARRAY_VALUE = 3;
66+
/**
67+
* Iterate using callback in form of function($value, $key)
68+
*/
69+
const EACH_VALUE_KEY = 4;
70+
5071
const UNPACK_ALL = 1;
5172
/**
5273
* Preserve arrays with highest nesting level (if they are not assoc) as element values instead of unpacking them
@@ -583,6 +604,52 @@ public static function mapObjects(array $objects, string $method, ...$args): arr
583604
return $return;
584605
}
585606

607+
/**
608+
* Traverse through array or iterable object and call callback for each element (ignoring the result).<br/>
609+
* <br/>
610+
* <b>Warning:</b> For <tt>EACH_VALUE_KEYS_LIST</tt> and <tt>EACH_KEYS_ARRAY_VALUE</tt> modes <tt>$iterable</tt> MUST be an array.
611+
*
612+
* @param array|Iterator|IteratorAggregate $iterable Usually array, but can be an iterable object.
613+
* @param callable $callback Callback function for each element of an iterable
614+
* @param int $mode What parameters and in which order should <tt>$callback</tt> receive
615+
* @return array|Iterator|IteratorAggregate Return unchanged input for chaining
616+
*/
617+
public static function each($iterable, callable $callback, int $mode = self::EACH_VALUE)
618+
{
619+
switch ($mode) {
620+
case self::EACH_KEY_VALUE:
621+
foreach ($iterable as $key => $value) {
622+
$callback($key, $value);
623+
}
624+
break;
625+
case self::EACH_VALUE_KEY:
626+
foreach ($iterable as $key => $value) {
627+
$callback($value, $key);
628+
}
629+
break;
630+
case self::EACH_VALUE_KEYS_LIST:
631+
foreach (self::unpack($iterable) as $dotKeys => $value) {
632+
$keys = self::getKeysArray($dotKeys);
633+
$callback($value, ...$keys);
634+
}
635+
break;
636+
case self::EACH_KEYS_ARRAY_VALUE:
637+
foreach (self::unpack($iterable) as $dotKeys => $value) {
638+
$keys = self::getKeysArray($dotKeys);
639+
$callback($keys, $value);
640+
}
641+
break;
642+
case self::EACH_VALUE:
643+
default:
644+
foreach ($iterable as $value) {
645+
$callback($value);
646+
}
647+
break;
648+
}
649+
650+
return $iterable;
651+
}
652+
586653
/**
587654
* Filter array values by preserving only those which keys are present in array obtained from $keys variable
588655
*

src/ArrObj.php

+7
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@
6363
*
6464
* ---------------------------------------------------------------------------------
6565
*
66+
* @method ArrObj each(callable $callback, int $mode = Arr::EACH_VALUE)
67+
* @see Arr::each()
68+
*
69+
* ---------------------------------------------------------------------------------
70+
*
6671
* @method ArrObj filterByKeys(mixed $keys, bool $exclude = false)
6772
* @see Arr::filterByKeys()
6873
*
@@ -168,6 +173,7 @@ class ArrObj implements IteratorAggregate, ArrayAccess, Countable
168173
'isArrayOfArrays',
169174
'map',
170175
'mapObjects',
176+
'each',
171177
'filterByKeys',
172178
'filterObjects',
173179
'group',
@@ -199,6 +205,7 @@ class ArrObj implements IteratorAggregate, ArrayAccess, Countable
199205
'remove',
200206
'map',
201207
'mapObjects',
208+
'each',
202209
'filterByKeys',
203210
'filterObjects',
204211
'group',

test/Arr/ArrTest.php

+46
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,52 @@ function test($arg = 0)
674674
$this->assertSame([3, 3, 3], $this->callMethod([$class, 'mapObjects'], $array, 'test', 2));
675675
}
676676

677+
/**
678+
* @param $class string|ArrObj
679+
* @dataProvider arrayClassProvider
680+
*/
681+
public function testEach($class)
682+
{
683+
foreach ($this->arrayProvider() as [$array]) {
684+
685+
// Check both pure array and iterable object
686+
foreach ([$array, new ArrayObject($array)] as $iterable) {
687+
// Just value
688+
$index = 0;
689+
$values = array_values($iterable instanceof ArrayObject ? $iterable->getArrayCopy() : $iterable);
690+
$this->callMethod([$class, 'each'], $iterable, function ($value) use ($values, &$index) {
691+
$this->assertSame($values[$index++], $value);
692+
}, Arr::EACH_VALUE);
693+
694+
// Also check default
695+
$index = 0;
696+
$this->callMethod([$class, 'each'], $iterable, function ($value) use ($values, &$index) {
697+
$this->assertSame($values[$index++], $value);
698+
});
699+
700+
// Key, Value
701+
$this->callMethod([$class, 'each'], $iterable, function ($key, $value) use ($iterable) {
702+
$this->assertSame($iterable[$key], $value);
703+
}, Arr::EACH_KEY_VALUE);
704+
705+
// Value, Key
706+
$this->callMethod([$class, 'each'], $iterable, function ($value, $key) use ($iterable) {
707+
$this->assertSame($iterable[$key], $value);
708+
}, Arr::EACH_VALUE_KEY);
709+
}
710+
711+
// Value, Keys list
712+
$this->callMethod([$class, 'each'], $array, function ($value, ...$keys) use ($class, $array) {
713+
$this->assertSame($this->callMethod([$class, 'get'], $array, $keys), $value);
714+
}, Arr::EACH_VALUE_KEYS_LIST);
715+
716+
// Keys array, Value
717+
$this->callMethod([$class, 'each'], $array, function ($keys, $value) use ($class, $array) {
718+
$this->assertSame($this->callMethod([$class, 'get'], $array, $keys), $value);
719+
}, Arr::EACH_KEYS_ARRAY_VALUE);
720+
}
721+
}
722+
677723
/**
678724
* @param $class string|ArrObj
679725
*

test/ArrTestCase.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
namespace Test;
33

44
use InvalidArgumentException;
5+
use Minwork\Helper\Arr;
56
use Minwork\Helper\ArrObj;
67
use PHPUnit\Framework\TestCase;
78
use ReflectionClass;
@@ -157,7 +158,7 @@ protected function callMethod(callable $callable, $array, ...$args)
157158
public function arrayClassProvider(): array
158159
{
159160
return [
160-
['\Minwork\Helper\Arr'],
161+
[Arr::class],
161162
[new ArrObj()],
162163
];
163164
}

0 commit comments

Comments
 (0)