Skip to content

Commit

Permalink
Implement value retrieval by matcher
Browse files Browse the repository at this point in the history
  • Loading branch information
yus-ham committed Jan 25, 2024
1 parent fbada75 commit a4e40b3
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 8 deletions.
34 changes: 26 additions & 8 deletions src/ArrayHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,9 @@ public static function parametrizedMerge(array $arrays, ?int $depth): array
* // Working with object:
* $username = \Yiisoft\Arrays\ArrayHelper::getValue($user, 'username');
*
* // Working with anonymous function:
* $fullName = \Yiisoft\Arrays\ArrayHelper::getValue($user, function ($user, $defaultValue) {
* return $user->firstName . ' ' . $user->lastName;
* // Retrieve the value by matcher function:
* $firstActiveMember = \Yiisoft\Arrays\ArrayHelper::getValue($users, function ($user, $key) {
* return $user->type === 'member' && $user->isActive;
* });
*
* // Using an array of keys to retrieve the value:
Expand All @@ -178,23 +178,22 @@ public static function parametrizedMerge(array $arrays, ?int $depth): array
*
* @param array|object $array Array or object to extract value from.
* @param array|Closure|float|int|string $key Key name of the array element,
* an array of keys, object property name, object method like `getName()`, or an anonymous function
* returning the value. The anonymous function signature should be:
* `function($array, $defaultValue)`.
* an array of keys, object property name, object method like `getName()` or an anonymous function. The anonymous function signature should be:
* `function($value, $key)`.
* @param mixed $default The default value to be returned if the specified array key does not exist. Not used when
* getting value from an object.
*
* @psalm-param ArrayKey|Closure $key
*
* @return mixed The value of the element if found, default value otherwise.
* @return mixed The value of the element if found or the return value of anonymous function is truthy, default value otherwise.
*/
public static function getValue(
array|object $array,
array|Closure|float|int|string $key,
mixed $default = null
): mixed {
if ($key instanceof Closure) {
return $key($array, $default);
return self::getValueByMatcher($array, $key, $default);
}

if (is_array($key)) {
Expand Down Expand Up @@ -253,6 +252,25 @@ private static function getRootValue(mixed $array, float|int|string $key, mixed
return $default;
}

private static function getValueByMatcher(
array|object $array,
Closure $match,
mixed $default = null
): mixed
{
if (is_object($array)) {
$array = self::getObjectVars($array);
}

foreach ($array as $key => $value) {
if ($match($value, $key)) {
return $value;
}
}

return $default;
}

/**
* Retrieves the value of an array element or object property with the given key or property name.
* If the key does not exist in the array or object, the default value will be returned instead.
Expand Down
20 changes: 20 additions & 0 deletions tests/ArrayHelper/GetValueTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,26 @@ public function testGetValueFromArray($key, $expected, $default = null): void
$this->assertEquals($expected, ArrayHelper::getValue($this->array, $key, $default));
}

public function testGetValueByMatcher(): void
{
$users = [
['name' => 'Cebe', 'status' => 'active'],
['name' => 'John', 'status' => 'not active'],
];

$activeUser = ArrayHelper::getValue($users, fn ($user) => $user['status'] === 'active');
$this->assertEquals('Cebe', $activeUser['name']);


$posts = [
new ArrayObject(['title' => 'hello world']),
new ArrayObject(['title' => 'hello test', 'tag' => 'test']),
];

$taggedPost = ArrayHelper::getValue($posts, fn ($post) => isset($post->tag));
$this->assertEquals('hello test', $taggedPost->title);
}

public function dataProviderGetValueByPathFromArray(): array
{
return array_merge($this->commonDataProviderFromArray(), [
Expand Down

0 comments on commit a4e40b3

Please sign in to comment.