2

I have a large array converted from a JSON structure with an unknown number of elements and sublevels.

Something like:

$marr = array
(
    "Order" => array
    (
        "Details" => array
        (
            "Document" => array
            (
                "Number" => "1585636772",
                "Date" => "2014-12-31"
            ),
            "Delivery" => array
            (
                "Date" => "2015-01-02",
                "TrackingCode" => "5703",
                "Name" => "Example Name",
                "Address" => "Example Address"
            )
        )
    )
);

And on the other hand, I have an array of items I need to compare and find out if they are in the array above. This "indexer" will always mirror the same structure above (it's generated before the comparison step) because I thought that would help me ensure a proper comparison in an easier way.

Something like:

$indexer = array
(
    "Order" => array
    (
        "Details" => array
        (
            "Document" => array
            (
                "Date" => "variable_name_1"
            ),
            "Delivery" => array
            (
                "Date" => "variable_name_2"
            )
        )
    )
);

I'm not entirely sure how best to compare these. I have looked into array_walk_recursive() which only returns the leaf values and I have tried to write my own attempts at a basic recursive function that would perform a foreach() which would then try to do something like:

if( isset($marr["Order"]["Details"]["Document"]["Date"]) )
{
    $store[ $indexer["Order"]["Details"]["Document"]["Date"] ] = $marr["Order"]["Details"]["Document"]["Date"];
}

So that at the end I would have a basic array that stored all values found on $marr under an alias that was listed on $indexer. Like this:

$store["variable_name_1"] = "2014-12-31";
$store["variable_name_2"] = "2015-01-02";

This has been a headache for two days now and I can't seem to figure out the best way to go through this. I'm trying to walk through $indexer to reach its ending, obtain the "variable name", and then compare with $marr to store its data, but I always seem to lose the parent nodes of $indexer while trying to do this recursively. I would appreciate any advice at all.

4
  • How do you get "variable_name_1" and two? Do these names matter? Commented Feb 23, 2016 at 12:33
  • Not sure, why you need an recursive function.. Just create an nested loop Commented Feb 23, 2016 at 12:33
  • @Kalkran those names are in $indexer, they are in theory needed because I want to store the data from the JSON web service to use in a bunch of SQL queries. They are just example names here, in theory I could have, says, twenty of these to use in five different queries. But that's a different logic step for the application I'm trying to build and not relevant here, I imagine. Commented Feb 23, 2016 at 12:38
  • @Philipp I don't think a basic nested loop would work here? Commented Feb 23, 2016 at 12:38

2 Answers 2

2

You could use this recursive function:

function storeFromIndex($marr, $indexer) {
    if (!is_array($indexer)) {
        return array($indexer => $marr);
    }
    $store = [];
    foreach($indexer as $key => $subindexer) {
        $store = array_merge($store, storeFromIndex($marr[$key], $subindexer));
    }
    return $store;
}

And then call it like this:

$store = storeFromIndex($marr, $indexer);

With the example data given, $store will be:

array (
  'variable_name_1' => '2014-12-31',
  'variable_name_2' => '2015-01-02',
)
Sign up to request clarification or add additional context in comments.

1 Comment

Jesus, it's perfect in its simplicity! Thank you so much.
2

Here I would like to suggest do not maintain indexer, you can use iterator and create new array using associated keys.

For example have a look on below solution:

$array = array
(
    "Order" => array
    (
        "Details" => array
        (
            "Document" => array
            (
                "Number" => "1585636772",
                "Date" => "2014-12-31"
            ),
            "Delivery" => array
            (
                "Date" => "2015-01-02",
                "TrackingCode" => "5703",
                "Name" => "Example Name",
                "Address" => "Example Address"
            )
        )
    )
);


$new_array = array();
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));

foreach ($iterator as $key => $value) {
    $keys = array();
    $keys[] = $key;
    for ($i = $iterator->getDepth() - 1; $i >= 0; $i--) {
        $keys[] = $iterator->getSubIterator($i)->key();
    }
    $key_paths = array_reverse($keys);
    $new_array[implode('_', $key_paths)] = $value;
}

print_r($array);
print_r($new_array);

Output:

Array
(
    [Order] => Array
        (
            [Details] => Array
                (
                    [Document] => Array
                        (
                            [Number] => 1585636772
                            [Date] => 2014-12-31
                        )

                    [Delivery] => Array
                        (
                            [Date] => 2015-01-02
                            [TrackingCode] => 5703
                            [Name] => Example Name
                            [Address] => Example Address
                        )

                )

        )

)
Array
(
    [Order_Details_Document_Number] => 1585636772
    [Order_Details_Document_Date] => 2014-12-31
    [Order_Details_Delivery_Date] => 2015-01-02
    [Order_Details_Delivery_TrackingCode] => 5703
    [Order_Details_Delivery_Name] => Example Name
    [Order_Details_Delivery_Address] => Example Address
)

1 Comment

This isn't a bad solution and I wasn't aware of those recursive iterator classes, thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.