使用带有 sql 的键值对搜索 php 多维关联数组,例如 '%LIKE%' 构造

Posted

技术标签:

【中文标题】使用带有 sql 的键值对搜索 php 多维关联数组,例如 \'%LIKE%\' 构造【英文标题】:search php multidimensional associative array using key value pair with sql like '%LIKE%' construct使用带有 sql 的键值对搜索 php 多维关联数组,例如 '%LIKE%' 构造 【发布时间】:2017-07-06 00:17:08 【问题描述】:

我有这个 php 函数,它可以很好地使用键值对搜索多维关联数组。我现在想扩展它以搜索键值对具有类似于 SQL 的构造的数组:name = '%john%'

function search($array, $key, $value)

    $results = array();
    like_search_r($array, $key, $value, $results);
    return $results[0];


function like_search_r($array, $key, $value, &$results)

    if (!is_array($array)) 
        return;
    

    if (isset($array[$key]) && $array[$key] == $value) 
        $results[] = $array;
    

    foreach ($array as $subarray) 
        like_search_r($subarray, $key, $value, $results);
    

我在这里找到了一个很好的例子filter values from an array similar to SQL LIKE '%search%' using PHP,但它只搜索一维数组。这个例子中的关键是 preg_grep 但我还没有想出如何在多维关联数组中使用它。任何帮助表示赞赏。

已编辑:我希望能够传递一组键值对来执行一个类似 sql 的过滤器。原始要求保持不变。过滤器必须支持类似于 sql '%like%' 的东西,不需要输入,满足组合匹配时返回根数组。如果键/值对不匹配,请忽略并继续下一个键/值对。我的输入数组如下所示:

     array('FIRST_NAME'=>'ma','MIDDLE_NAME'=>'bill',
     'LAST_NAME'=>'jo','ALIASES'=>'phil',
     'DOB'=>'2017-07-05','COUNTRY_OF_BIRTH'=>'Jamaica',
     'Countries1'=>array(array('COUNTRY_CODE'=>'JM'),array('COUNTRY_CODE'=>'AL')),
     'Countries2'=>array(array('COUNTRY_CODE'=>'JM'),array('COUNTRY_CODE'=>'AL')));

可以在此处找到要过滤的示例数组:https://www.tehplayground.com/dIMKbb6Tcw5YU38R

【问题讨论】:

【参考方案1】:

我认为要走的路是preg_match()

function match($search, $subject)

    $search = str_replace('/', '\\/', $search);

    return preg_match("/$search/i", (string)$subject);


function like_search_r($array, $key, $value, array &$results = [])

    if (!is_array($array)) 
        return;
    

    $key   = (string)$key;
    $value = (string)$value;

    foreach ($array as $arrayKey => $arrayValue) 
        if (match($key, $arrayKey) && match($value, $arrayValue)) 
            // add array if we have a match
            $results[] = $array;
        

        if (is_array($arrayValue)) 
            // only do recursion on arrays
            like_search_r($arrayValue, $key, $value, $results);
        
    


$array1 = [
    'foo'    => 'bar',
    'subarr' => [
        'test'                 => 'val',
        'dangerous/characters' => 1,
    ],
];

$results1 = [];
like_search_r($array1, 'fo', 'bar', $results1);
print_r($results1);

/*
Array
(
    [0] => Array
        (
            [foo] => bar
            [subarr] => Array
                (
                    [test] => val
                    [dangerous/characters] => 1
                )

        )

)
*/

$results2 = [];
like_search_r($array1, 'est', 'val', $results2);
print_r($results2);

/*
Array
(
    [0] => Array
        (
            [test] => val
            [dangerous/characters] => 1
        )

)
*/

$results3 = [];
like_search_r($array1, 's/c', 1, $results3);
print_r($results3);

/*
Array
(
    [0] => Array
        (
            [test] => val
            [dangerous/characters] => 1
        )

)
*/

根据您的评论调整:

function match($search, $subject)  /* no change */ 

function like_search_r($array, $key, $value, array &$results = [], $level = 0)

    if (!is_array($array)) 
        return false;
    

    $key   = (string)$key;
    $value = (string)$value;

    $found = false;

    foreach ($array as $arrayKey => $arrayValue) 
        if (match($key, $arrayKey) && match($value, $arrayValue)) 
            return true;
        

        if (is_array($arrayValue)) 
            // only do recursion on arrays
            // results are only added on top level
            if (like_search_r($arrayValue, $key, $value, $results, $level+1)) 
                if ($level == 1) 
                    $results[] = $array;
                
                $found = true;
            
        
    

    return $found;


$array2   = [['id' => 0, 'values' => ['name' => 'bill']], ['id' => 1, 'values' => ['name' => 'john']]];
$results4 = [];
like_search_r($array2, 'name', 'john', $results4);
print_r($results4);

/*
Array
(
    [0] => Array
        (
            [id] => 1
            [values] => Array
                (
                    [name] => john
                )

        )

)
*/

【讨论】:

它确实有效,但唯一的问题是它区分大小写。因此,如果存储的值是“Mark”并且我搜索“ma”,我不会得到结果。但是,如果我搜索“Ma”,我确实会得到结果。此外,第三个测试对我不起作用,但它对我来说并不是一个重要的用例。让它不区分大小写,我会给你 50 分。 我已经改变了它,不区分大小写。这只是匹配模式之后的i 我试图奖励你,但它说我必须等待 13 小时。 有没有办法让它从顶部节点数组而不是子数组返回数组?例如数组( [0]=>[[id]=>0,values['name']=>'bill'], [1]=>[[id]=>1,values['name'=> '约翰']]);如果搜索 name = john,我不仅希望获取值数组,还希望从根节点 [1] 获取。这可能吗? 如果它可以如上所述从根节点返回,那将是我的用例的完美选择。

以上是关于使用带有 sql 的键值对搜索 php 多维关联数组,例如 '%LIKE%' 构造的主要内容,如果未能解决你的问题,请参考以下文章

PHP使用字符串替换从多维数组中的键值替换关键字

如何在键具有数组的多维数组中求和所有相同的键值?

PHP数组简介

如何在 Lua 的键值对表中弹出/删除下一个项目(任何)?

PHP从多个json文件中的键值排序结果

ng-options 中的键值对