php搜索未知深度的多维数组

时间:2015-04-23 01:41:33

标签: php arrays json search recursion

我尝试选择由json_decode()构造的数组的数据。 原则上它是一个未知维度的多重阵列。

首先,我想以递归方式搜索此数组中的值。作为下一步,我想获得上层维度的其他一些值。所以这是一个例子:

我搜索:"2345"

....
$json[3][6]['journal']['headline']="news"
$json[3][6]['journal']['article']=2345
....
$json[8]['journal']['headline']="weather"
$json[8]['journal']['article']=2345
....

之后我想得到元素headline的值(返回“新闻”和“天气”)

可能是元素2345可以在不同维度找到!!!

2 个答案:

答案 0 :(得分:0)

Someone could probably do this with a RecursiveIteratorIterator object, but I personally have a hard time with iterator objects, so here is a fairly robust system:

<?php
// This will traverse an array and find the
// value while storing the base key    
class RecurseLocator
    {
        public  static  $saved = array();
        public  static  $find;
        public  static  $trigger;
        public  static  function Initialize($find = false)
            {
                self::$find =   $find;
            }

        public  static  function Recursive(array $array)
            {
                foreach($array as $key => $value) {

                        if(!isset(self::$trigger) || (isset(self::$trigger) && empty(self::$trigger))) {
                                if(is_numeric($key))
                                    self::$trigger  =   $key;
                            }

                        if(!is_array($value)) {
                                if($value == self::$find) {
                                        self::$saved[self::$trigger]    =   $value;
                                    }
                            }

                        if(is_array($value)) {

                                $value  =   self::Recursive($value);
                                if(!is_numeric($key))
                                    self::$trigger  =   "";
                            }


                        $return[$key]   =   $value;
                    }

                return $return;
            }
    }

// This class will traverse an array searching
// for a specific key or keys
class   RecurseSearch
    {
        public  $data;
        public  $compare;

        public  function Find($array = '',$find,$recursive = true)
            {
                $find   =   (is_array($find))? implode("|",$find):$find;
                if(is_array($array)) {

                        foreach($array as $key => $value) {

                        if(preg_match("/$find/",$key))
                            $this->compare[$key]    =   $value;

                                if($recursive == true) {
                                        if(!is_array($value)) {
                                                if(preg_match("/$find/",$key)) {
                                                        $this->data[$key][] =   $value;
                                                    }

                                                $array[$key]    =   $value;
                                            }
                                        else {
                                                if(preg_match("/$find/",$key))
                                                    $this->data[$key][] =   $this->Find($value,$find);

                                                $array[$key]    =   $this->Find($value,$find);
                                            }
                                    }
                                else {
                                        if(preg_match("/$find/",$key))
                                            $this->data[$key]   =   $value;
                                    }
                            }

                        $this->data =   (isset($this->data))? $this->data:false;

                        return $this;
                    }
            }
    }

// This function just wraps the RecurseSearch class
function get_key_value($array = array(), $find = array(),$recursive = true)
    {
        $finder =   new RecurseSearch();
        return $finder->Find($array,$find,$recursive);
    }

USAGE:

    $json[3][6]['journal']['headline']  =   "news";
    $json[3][6]['journal']['article']   =   2345;
    $json[8]['journal']['headline']     =   "weather";
    $json[8]['journal']['article']      =   2345;
    $json[4][1]['journal']['headline']  =   "news";
    $json[4][1]['journal']['article']   =   22245;
    $json[5]['journal']['headline']     =   "weather";
    $json[5]['journal']['article']      =   233345;

    // Set the search criteria
    RecurseLocator::Initialize(2345);
    // Traverse the array looking for value
    $arr    =   RecurseLocator::Recursive($json);
    // If found, will be stored here
    $iso    =   RecurseLocator::$saved;

    /* $iso looks like:
    Array
    (
        [3] => 2345
        [8] => 2345
    )
    */

    // Loop through the $iso array
    foreach($iso as $key => $value) {
            // Save to new array your search results
            $new[]  =   get_key_value($json[$key],array("headline","article"),true);
        }

    /* $new looks like:
Array
(
    [0] => RecurseSearch Object
        (
            [data] => Array
                (
                    [headline] => Array
                        (
                            [0] => news
                        )

                    [article] => Array
                        (
                            [0] => 2345
                        )
                )

            [compare] => Array
                (
                    [headline] => news
                    [article] => 2345
                )
        )

    [1] => RecurseSearch Object
        (
            [data] => Array
                (
                    [headline] => Array
                        (
                            [0] => weather
                        )

                    [article] => Array
                        (
                            [0] => 2345
                        )
                )

            [compare] => Array
                (
                    [headline] => weather
                    [article] => 2345
                )
        )
)
    */
?>

Just as a side note, the above class stores multiple found in the [data], and then stores them also in the [compare], however the [compare] will overwrite itself if multiple same-keys are found in one array where as [data] will just keep adding values.

答案 1 :(得分:0)

只需创建一个编译未知数组的函数。试试这个

$json[1][6]['journal']['headline']="news";
$json[1][6]['journal']['article']=2345;
$json[3][6]['journal']['headline']="HOT";
$json[3][6]['journal']['article']=2345;
$json[8]['journal']['headline']="weather";
$json[8]['journal']['article']=2345;
$json[10]['journal']['headline']="weather";
$json[10]['journal']['article']=2345;

$GLOBALS['list_scan'] = array();
$result = array();

foreach ($json as $key => $value) 
{
    if (is_array($value)) {
        _compile_scan($key, $value);
    }
}

echo "<pre>";
print_r($GLOBALS['list_scan']);
echo "</pre>";

$search = "2345";
$keyword = "article";
$keyFinder = "headline";

foreach ($GLOBALS['list_scan'] as $key => $value)
{
    if ($value == $search)
    {
        $addr = substr($key, 0, -(strlen($keyword))).$keyFinder;
        if (!empty($GLOBALS['list_scan'][$addr]))
        {
            $result[] = $GLOBALS['list_scan'][$addr];
        }
    }
}
echo "<pre>";
print_r($result);
echo "</pre>";


function _compile_scan($index, $value)
{
    $pointer =& $GLOBALS['list_scan'];

    foreach ($value as $key => $val) 
    {
        $temp = '';
        $temp = $index.'|'.$key;
        if (is_array($val))
        {
            // $pointer[$temp] = $val;
            _compile_scan($temp, $val);
        }
        else $pointer[$temp] = $val;
    }
}

输出:

Array
(
    [1|6|journal|headline] => news
    [1|6|journal|article] => 2345
    [3|6|journal|headline] => HOT
    [3|6|journal|article] => 2345
    [8|journal|headline] => weather
    [8|journal|article] => 2345
    [9|journal|headline] => Others
    [9|journal|article] => 234521
)
Array
(
    [0] => news
    [1] => HOT
    [2] => weather
)