0

Lets say I have an array of objects.

I want to see if any of the objects has the name property of foo.

In other languages like C# there is easy way to evaluate it like:

objArray.Contains(x => x.Name == "foo");

In PHP is there are better way to do it than this:

$hasFoo = false;
foreach($objs as $obj)
{
    if($obj->name == "foo")
    {
        $hasFoo = true;
        break;
    }
}
Guerrilla
  • 13,375
  • 31
  • 109
  • 210
  • 2
    That is the most efficient way to do it. You could use something like [`array_reduce`](https://www.php.net/manual/en/function.array-reduce.php) but none of the PHP array functions have a way of breaking out of a loop so will process the entire array even if they find a match in the first element. – Nick Nov 29 '19 at 00:10
  • [link](https://stackoverflow.com/questions/4742903/php-find-entry-by-object-property-from-an-array-of-objects) Dublicates – zac Nov 29 '19 at 00:15
  • You can use this answer: https://stackoverflow.com/a/26524231/283322 – zac Nov 29 '19 at 01:11

2 Answers2

1

There is none (as of PHP 7.3).

You could use a clearer, but less efficient syntax using array_reduce():

function satisfies(array $objectArray, $callback) {
    return array_reduce(
        $objectArray,
        function($found, $item) use ($callback) {
            return $found || call_user_func($callback, $item);
        },
        false
    );
}


$has = satisfies($array, function($obj) { return $obj->name === 'foo'; });

The function will call iteratively the callback until it returns true, then it will continue walking the whole array (albeit reasonably quickly). If no element in the array returns a truthy value, the function returns false.

Issuing a call and passing an object at each iteration, the function is slower than a plain foreach.

And, as @Jeto very correctly pointed out, I have over-engineered it. Could have written

function satisfies(array $objectArray, $callback, $ifFound = true, $ifNotFound = false) {
    foreach ($objectArray as $obj) {
        if (call_user_func($callback, $obj)) {
            return $ifFound;
        }
    }
    return $ifNotFound;
}
LSerni
  • 55,617
  • 10
  • 65
  • 107
  • 1
    If you're gonna make a function, why not just use a simple loop and return when needed? e.g. https://github.com/lstrojny/functional-php/blob/master/src/Functional/Some.php – Jeto Nov 29 '19 at 01:08
  • @Jeto you are completely right. Amended answer, – LSerni Nov 29 '19 at 10:23
1

Not better but you can filter and check if empty or not or cast to Boolean with (bool):

$hasFoo = array_filter($objs, funtion($v) { return $v->name === ‘foo’; });


$hasFoo = (bool)array_filter($objs, funtion($v) { return $v->name === ‘foo’; });
AbraCadaver
  • 78,200
  • 7
  • 66
  • 87