phparraysfilterkeyassociative-array

Filter a flat associative array to only keep elements where related keys share the same suffix


I have a dynamic array as

[
    "question" => "test 1",
    "question1" => "hello test 1",
    "question2" => "hello test 2 checked",
    "homepage2" => "homepage",
    "question3" => "3 test checked",
    "homepage3" => "homepage",
    "question4" => "question 4 ? checked",
]

keys are "question", "question1"...etc and "homepage","homepage1"..etc so i want to display only the values from the array when the index is question($number) and has similar key as homepage($number)

How to make it look like the following?

[
    "question2" => "hello test 2 checked",
    "homepage2" => "homepage",
    "question3" => "3 test checked",
    "homepage3" => "homepage",
]

Solution

  • You could first create an array keyed by the suffix numbers, and store as value an array of all key/value pairs where the key has that suffix number. Then you would filter those that have two such key/value pairs, and arrange those in the format you need:

    $arr = [
      "question"=> "test 1",
      "question1"=> "hello test 1",
      "question2"=> "hello test 2 checked",
      "homepage2"=> "homepage",
      "question3"=> "3 test checked",
      "homepage3"=> "homepage",
      "question4"=> "question 4 ? checked",
    ];
    
    $temp = [];
    foreach($arr as $key => $value) {
        if (preg_match("/^(question|homepage)(\d+)$/", $key, $parts))
            $temp[$parts[2]][$parts[0]] = $value;
    }
    $result = [];
    foreach($temp as $num => $pair) {
        if (count($pair) == 2) $result = array_merge($result, $pair);
    }
    
    print_r($result);
    

    $result will be:

    Array (
        "question2" => "hello test 2 checked",
        "homepage2" => "homepage",
        "question3" => "3 test checked",
        "homepage3" => "homepage"
    )
    

    See it run on eval.in.

    More logical structure

    I would however suggest the more logical structure where you group question and homepage together in a pair (array), and assign that to a key which is the number of that pair. In that case the two loops need minor changes:

    $temp = [];
    foreach($arr as $key => $value) {
        if (preg_match("/^(question|homepage)(\d+)$/", $key, $parts))
            $temp[$parts[2]][$parts[1]] = $value;
    }
    $result = [];
    foreach($temp as $num => $pair) {
        if (count($pair) == 2) $result[$num] = $pair;
    }
    

    This will give the following structure:

    Array(
        "2" => Array(
            "question" => "hello test 2 checked",
            "homepage" => "homepage"
        ),    
        "3" => Array(
            "question" => "3 test checked",
            "homepage" => "homepage"
        )
    )
    

    See it run on eval.in.