首页 > 解决方案 > 如何在 PHP 中识别数组中的不匹配元素

问题描述

鉴于存在大量元素(例如 ID 列表)。

$setOfIds = $externalSource->getElementsIds();
// gives sth. like => $setOfIds = ['1b23', '2c18', 'h23a', …];

假设有一个函数可以确定完整集或任何给定子集是否与某些搜索条件匹配,但不识别与条件不匹配的特定元素(即通过对集合的数据库查询)。

$database->hasIds($setOfIds); // returns true if all ids given with the set are found in database

如何在不循环整个集合的情况下识别匹配搜索条件的元素。

$missingIds = findMissing($setOfIds); // how would findMissing() be implemented?

鉴于数据库中没有具有 id 的元素,h23a$setOfIds其中$setOfIds确实包含数百或数千个 id,所有这些 id 都将在数据库中找到,运行待实现方法的结果应解析为

$missingIds == ['h23a'];

标签: phparrays

解决方案


这可以通过类似于 git 的bisect的递归函数或将给定检查函数应用于元素集的左侧和右侧部分的二进制搜索以通用方式完成。

/**
 * Recursively searches for elements in $elements that match search-critearia checked by $callback
 * Inspects two halfs of an array with itself if check-function return false on complete set of elements
 *
 * @param array    $elements the set of elements to check
 * @param callable $callback pass a function that checks the set and returns true if search criteria apply, false else
 *
 * @return array   list of elements that match the criteria checked by callback
 */
function bisect(array $elements, callable $callback) : array {
    // $elements is an empty array at the end of the recursion, when the remaining 1-sized set of element was sliced
    // when the complete matches the criteria checked by $callback, there is no need for further recursion
    if (empty($elements) || false === $callback($elements)) {
        return [];
    }

    // set only has one remaining element and callback returned false on it => identified an element that matches criteria
    if (1 === count($elements)) {
        return $elements;
    }

    $sectionSize = count($elements)/2; 
    $left = array_slice($elements, 0, $sectionSize);
    $right = array_slice($elements, $sectionSize);

    return array_merge(bisect($left, $callback), bisect($right, $callback));
}

给定来自问题的数据,可以像这样识别元素:

$missingIds = bisect(
   $setOfIds,
   function ($ids) use ($database) { return !$database->hasIds($ids); }
);

推荐阅读