skip to Main Content

How would you extract every value of a key regardless of how deep or shallow it is in an array.

Here is a sample JSON array. I want to grab every occurrence of "content" and concatenate them into a single string.

{
  "foo": [
    "content": "hi",
    "inner": []
  ],
  "bar": [
    "content": "hi2",
    "inner": [
      {
        "bat": [
          "content": "hi3",
          "inner": []
        ],
      }
    ]
  ]
}

Theoretically that could go on for ever with inner of inner of inner. How do we grab all the content values?

3

Answers


  1. I would use array_walk_recursive() for this, as it is pretty straightforward.

    //convert JSON to an array
    $data = json_decode($json_data, true);
    
    //create an empty array to hold all of the values we are collecting
    $content_values = [];
    
    //this `function` is called for every key in the array that does not contain another array as it's value
    //We also pass $content_values as a reference, so we can modify it inside the function
    array_walk_recursive($data, function ($value, $key) use (&$content_values) {
        if ($key === 'content') {
            $content_values[] = $value;
        }
    });
    
    //Lastly, implode all of the array elements into a string with the given separator
    $concatenated_content = implode(', ', $content_values);
    echo $concatenated_content;
    

    Output

    hi, hi2, hi3
    
    Login or Signup to reply.
  2. You have to create a function that will take the array value. It will check for every array element. If the array element is an array then it will call itself again otherwise the the value will stored in another array.

    The new array will be the expected result. For any dimension of the array, it will work.

    function extractKeyValues($data, $key)
    {
        $values = [];
    
        foreach ($data as $element) {
            if (is_array($element)) {
                $values = array_merge($values, extractKeyValues($element, $key));
            } elseif (is_string($element) && $key === 'content') {
                $values[] = $element;
            }
        }
    
        return $values;
    }
    
    $jsonData = '{
        "foo": [
            {
                "content": "hi",
                "inner": []
            }
        ],
        "bar": [
            {
                "content": "hi2",
                "inner": [
                    {
                        "bat": [
                            {
                                "content": "hi3",
                                "inner": []
                            }
                        ]
                    }
                ]
            }
        ]
    }';
    
    $dataArray = json_decode($jsonData, true);
    $contentValues = extractKeyValues($dataArray, 'content');
    
    $result = implode(' ', $contentValues);
    
    Login or Signup to reply.
  3. Here you go:

    INPUT:

    $array = [
        "foo" => [
            "content" => "hi",
            "inner" => []
        ],
        "bar" => [
            "content" => "hi2",
            "inner" => [
                "bat" => [
                  "content" => "hi3",
                  "inner" => []
                ]
            ]
        ],
        "biz" => [
            "content" => "hi4",
            "inner" => [
                "bat" => [
                  "content" => "hi5",
                  "inner" => [
                        "bong" => [
                            "content" => "bong",
                            "inner" => [
                                "bat" => [
                                  "content" => "bong0",
                                  "inner" => []
                                ]
                            ]
                        ],
                        "bong1" => [
                            "content" => "bong1",
                            "inner" => [
                                "bong2" => [
                                  "content" => "bong2",
                                  "inner" => []
                                ]
                            ]
                        ]
                  ]
                ]
            ]
        ]
    ];
    

    Recursive Function

        function getContent($array){
            
            $content = [];
            
            foreach($array as $row){
                foreach($row as $key => $value){
                    switch($key){
                        case 'content':
                            $content[] = $value;
                        break;
                        case 'inner':
                            $content = array_merge($content, getContent($value)); //recurse
                        break;
                    }
                }
            }
    
            return $content;
        }
        
        print_r( getContent($array) );
        
    

    Results

    Array
    (
        [0] => hi
        [1] => hi2
        [2] => hi3
        [3] => hi4
        [4] => hi5
        [5] => bong
        [6] => bong0
        [7] => bong1
        [8] => bong2
    )
    

    You can use ‘implode’ and whatever separator you like. I prefer building an array and then imploding it.

    PS. someone already took array_walk_recursive – the other answer I believe is incomplete.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search