PHP Classes

File: find.php

Recommend this page to a friend!
  Classes of Nathaniel Sherwood   Encase PHP Functional Programming   find.php   Download  
File: find.php
Role: Example script
Content type: text/plain
Description: Example script
Class: Encase PHP Functional Programming
Make functions work as if they are class functions
Author: By
Last change:
Date: 5 years ago
Size: 3,263 bytes
 

Contents

Class file image Download
<?php
namespace Encase\Functional;

/**
 * Searches forward through the value for a given sub-value.
 *
 * Returns an array containing index/key and the value if found, boolean FALSE
 * is returned if no match is found. Indexes are returned for indexed arrays
 * and strings, while string keys are returned for objects and assoc arrays.
 *
 * `$pred` can be a value, in which case a match is found using strict
 * comparison in the case of arrays. In the case of strings, PHP's strpos is
 * used, with which any value not a string will be converted to an int and
 * tested as an ordinal value of the character.
 *
 * If `$pred` is a `\Closure` or `\Encase\Functional\Func`, then the predicate
 * is always used. However, due to ambiguity in PHP callables, a string or
 * array predicate will not be treated as a function if `$value` is a `string`
 * or `array`. Prefer to always use `\Encase\Functional\Func` for callables
 * that are not closures.
 *
 * This function attempts to use the native PHP functions `array_search` and
 * `mb_strpos` when the predicate is not unambiguously a function.
 *
 * @param array|string|iterable|stdClass $value Value to search in.
 * @param mixed|\Closure|\Encase\Functional\Func $pred
 * A predicate function to perform the comparison or a value.
 * If null, the first truthy value will be returned.
 * @param int $offset Index to begin searching at.
 * @return array|bool Returns [index/key, value] if found, otherwise FALSE.
 */
function find($value, $pred = null, int $offset = 0)
{
   
$type = assertType($value, ['\Traversable', 'iterable', 'string', 'stdClass', 'null'], 'value');

    if (empty(
$value)) {
        return
false;
    }

    if (\
is_null($pred)) {
       
$pred = function ($value) {
            return
$value != false;
        };
    }

   
$predIsFunction = isType($pred, 'function');

   
// Prevent also passing the index to PHP internal functions.
   
if ($pred instanceof Func && $pred->isInternal()) {
       
$pred = function ($value) use ($pred) {
            return
$pred($value);
        };
    }

    if (
$type === 'string') {
        if (!\
function_exists('mb_strpos')) {
           
$pred = function ($value) use ($pred) {
                return
$value === $pred;
            };

           
$predIsFunction = 'function';
        }

        if (
$predIsFunction) {
           
$iterable = new \LimitIterator(new \ArrayIterator(split($value)), $offset);

           
$result = each($iterable, function ($char, $index) use ($pred) {
                if (
$pred($char, $index)) {
                    return [
$index, $char];
                }
            });

            return
$result !== null ? $result : false;
        }

       
$pos = \mb_strpos($value, $pred, $offset);
        return
$pos !== false ? [$pos, \mb_substr($value, $pos, 1)] : false;
    }

    if (\
is_array($value) && !$predIsFunction) {
        if (
$offset) {
           
$value = \array_slice($value, $offset, null, true);
        }

       
$key = \array_search($pred, $value, true);
        return
$key !== false ? [$key, $value[$key]] : false;
    }

    if (!\
is_callable($pred)) {
       
$pred = function ($value) use ($pred) {
            return
$value === $pred;
        };
    }

    if (
$value instanceof \IteratorAggregate) {
       
$iterator = $value->getIterator();
    } else {
       
$iterator = new \ArrayIterator($value);
    }

   
$iterable = new \LimitIterator($iterator, $offset);

    foreach (
$iterable as $key => $val) {
        if (
$pred($val, $key)) {
            return [
$key, $val];
        }
    }

    return
false;
}