0

What i'm trying to achieve is to get this input array:

$input = [
    "AccountId" => "18",
    "Id" => "53600065",
    "Name" => "Awesome Test Company From SS",
    "Financial" => [
         "vat" => "12345",
    ]
]

Turned into something like this output array:

$output = [
    "account_id" => "18",
    "master_id" => "53600065",
    "name" => "Awesome Test Company From SS",
    "financial_data" => [
         "vat_number" => "12345"
    ]

]

The input can have one or more fields that needs to be mapped. So it could easily look like this as well:

$input2 = [
    "AccountId" => "18",
    "Street" => "Some Street 123",
    "Country" => "England",
    "Contacts" => [
       [
          "Id" => "1234",
          "Name" => "John Doe",
       ]
    ]
]

And have output looking like this:

$output2 = [
    "account_id" => "18",
    "street_name" => "Some Street 123",
    "country" => "England",
    "contacts" => [
       [
          "contact_id" => "1234",
          "name" => "John Doe",
       ]
    ]
]

So basically I want to map the keys from one array to another. The input can have more keys than shown above, and can have nested arrays as values. I also know all the input keys I need to supports, but they are not guaranteed to be part of the input array on every request.

My naive solution is to build an array like this

$result = [];
if (array_key_exists('AccountId', $input) {
    $result = array_merge($result, ['account_id' => $input['AccountId']]);
}
if (array_key_exists('Id', $input) {
    $result = array_merge($result, ['master_id' => $input['Id']]);
}
...

But this becomes messy really quick, it's not flexible, and in simply just looks bad. But how can I achieve this in a good matter? Basically I need to map some values ['AccountId' => 'account_id', 'Id' => 'master_id'], but I can't seem to figure out how to do this properly. I would love to be able to traverse the array recursively, and then map the values, but how can I do this, if the structure of the output array is not necceseraly the same as the input, and the keys needs new names?

Jonas Lomholdt
  • 1,215
  • 14
  • 23
  • I'd create a `$mapping` array with all the keys you need to support. Something like `["AccountId" => "account_id", "Id" => "master_id", ...]` I would then iterate over that and, for each key, check if it exists in the input array. If it exists, add the value into your output array, using the key from `$mapping`. – domsson Jul 03 '17 at 13:46
  • Can you provide a second input array, so that we can see some differences? (and your desired output for it) – mickmackusa Jul 03 '17 at 13:55
  • For a brief second, I thought I was going to get the chance to use `array_change_key_case()` for the first time in my life... no such luck. – mickmackusa Jul 03 '17 at 14:14
  • Please include your expected output for `$input2` As is, your question is at risk of being closed as "unclear what you are asking". Please help us to help you. – mickmackusa Jul 03 '17 at 14:15
  • Correction, this question may be "too broad". – mickmackusa Jul 03 '17 at 14:20
  • I have added some more examples input/output. Might I have several mappings for each subarray and use those to map against. Then arbitrary id's wouldn't be a problem i suppose. – Jonas Lomholdt Jul 03 '17 at 14:20
  • After your latest edit, I am now leaning toward "too broad". Why are you doing all of this manipulation on the keys? Where is this going in your program that the keys must be changed? Are you always going to change every elements' key? Even after posting two sample inputs and their desired results, your question is not clear enough to offer a quality answer. – mickmackusa Jul 03 '17 at 14:29

1 Answers1

0

The solution using array_intersect_key and array_combine functions:

$keys_map = [
    'AccountId' => 'account_id',
    'Id' => 'master_id',
    'Name' => 'name'
];
$intersection = array_intersect_key($input, $keys_map);
$result = [];

if (count($intersection) == count($keys_map)) {  // if all keys from $keys_map were matched
    $result = array_combine($keys_map, $intersection);
}

print_r($result);

The output:

Array
(
    [account_id] => 18
    [master_id] => 53600065
    [name] => Awesome Test Company From SS
)

http://php.net/manual/en/function.array-intersect-key.php

RomanPerekhrest
  • 88,541
  • 4
  • 65
  • 105
  • 1
    But this doesn't solve the problem of missing elements. OP says: "I also know all the input keys I need to supports, but they are not guaranteed to be part of the input array on every request." – mickmackusa Jul 03 '17 at 13:59
  • This is a nice attempt @RomanPerekhrest but as mickmackusa says, this will only work if the input is exactly equal to the mapping. But i can't guarantee that unfortunately. – Jonas Lomholdt Jul 03 '17 at 14:07
  • @JonasLomholdt, so your dynamic rules are unclear. How should I know that there is an arbitrary key `Id` which should become `account_id` ? – RomanPerekhrest Jul 03 '17 at 14:09
  • @JonasLomholdt I agree with Roman, your question needs more clarity. Please add more examples as I have requested under your question. – mickmackusa Jul 03 '17 at 14:09