Объединение многомерного массива в PHP на основе значения ключа

У меня есть два объекта JSON, которые я конвертирую в массивы. Мне нужно объединить два массива на основе общего ключа ("locationCode") и добавить данные массива "адрес" из одного массива в другой.

После того, как я успешно извлек JSON с удаленного сервера с помощью CURL, я конвертирую их в массивы:

$json1 = json_decode($jsonresult, true);
$json2 = json_decode($jsonresult2, true);

Полученные массивы выглядят следующим образом:

$json1:

"maxResults":500,
"events":[
  {
     "eventCode":"20140001",
     "eventId":"72",
     "contact":{
        "contactName":"John Doe",
        "organization":"John Doe Inc.",
        "notes":""
     },
     "location":{
        "locationName":"Company Factory",
        "locationCode":"factory",
        "email":"",
        "phone":"866-123-4567",
        "tollfree":"",
        "fax":"",
        "url":"",
        "notes":""
     },
     "timezone":"(GMT-08:00) Pacific Time (US & Canada)",
     "primaryFormURL":"path/to/form"
  },
  {
     "eventCode":"20140002",
     "eventId":"73",
     "contact":{
        "contactName":"John Doe",
        "organization":"John Doe Inc.",
        "notes":""
     },
     "location":{
        "locationName":"Company HQ",
        "locationCode":"hq",
        "email":"",
        "phone":"866-123-4567",
        "tollfree":"",
        "fax":"",
        "url":"",
        "notes":""
     },
     "timezone":"(GMT-08:00) Pacific Time (US & Canada)",
     "primaryFormURL":"path/to/form"
  },
  {
     "eventCode":"20140003",
     "eventId":"74",
     "contact":{
        "contactName":"John Doe",
        "organization":"John Doe Inc.",
        "notes":""
     },
     "location":{
        "locationName":"Company HQ",
        "locationCode":"factory",
        "email":"",
        "phone":"866-123-4567",
        "tollfree":"",
        "fax":"",
        "url":"",
        "notes":""
     },
     "timezone":"(GMT-08:00) Pacific Time (US & Canada)",
     "primaryFormURL":"path/to/form"
  }
]

$json2:

"maxResults":500,
"locations":[
  {
     "numberOfRooms":null,
     "totalSpace":null,
     "address":{
        "line1":"1245 Anystreet, Building 600",
        "line2":"",
        "line3":"",
        "line4":"",
        "city":"Anycity",
        "state":"CA",
        "postalCode":"98765",
        "country":"United States",
        "intlState":""
     },
     "locationCode":"factory",
     "desc":"",
     "url":""
  },
  {
     "numberOfRooms":null,
     "totalSpace":null,
     "address":{
        "line1":"3421 Anystreet, Building 200",
        "line2":"",
        "line3":"",
        "line4":"",
        "city":"Anycity",
        "state":"CA",
        "postalCode":"97654",
        "country":"United States",
        "intlState":""
     },
     "locationCode":"hq",
     "desc":"",
     "url":""
  }
]

Теперь мне нужно соединить два массива на основе совпадения ключей «locationCode». Соединение будет состоять из добавления данных массива «адрес» из $json2 в $json1 в соответствующей совпадающей позиции массива. Я пробовал различные итераторы многомерных массивов, но мне трудно понять, как на самом деле выборочно перемещать нужные мне значения из одного массива в другой. У меня есть итератор, который находит совпадения, например:

$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($json1));
$iterator2 = new RecursiveIteratorIterator(new RecursiveArrayIterator($json2));
    foreach($iterator as $key1=>$value1) {
        if($key1=="locationCode") {
            foreach($iterator2 as $key2=>$value2) {
                if($key2=="locationCode" && $value1==$value2){
                    echo $key1.' -- '.$value1.':::'.$key2.' -- '.$value2.'<br />';
                }
            }

        }
    }

Это успешно выводит совпадающие значения. Как мне теперь получить данные массива «адрес» и добавить их в позицию в $json1, где было идентифицировано совпадение?


person Maxwell Donnelly    schedule 17.01.2014    source источник
comment
каковы ваши критерии для соответствия местоположения и адреса?   -  person user2936213    schedule 17.01.2014
comment
значение locationCode будет таким же.   -  person Maxwell Donnelly    schedule 18.01.2014


Ответы (1)


Я бы сначала обработал json2 в новый массив со значениями locationCode в качестве ключей и адресными объектами в качестве значений. Затем я просматривал массив событий и добавлял к нему адрес, если вы можете найти совпадение с кодом местоположения в этом массиве.

$json1 = json_decode($jsonresult);
$json2 = json_decode($jsonresult2);
// map locations to associative array
$addresses = array();
foreach($json2['locations'] as $location) {
    $addresses[$location->locationCode] = $location->address;
}
// add addresses to events
$events = $json1['events'];
array_walk($events, function (&$event, $key_not_used, $addresses) {
    if(array_key_exists($event->locationCode, $addresses)) {
        $event->address = $addresses[$event->locationCode];
    }
});

Обновление OP: вот окончательный рабочий код...

$json1 = json_decode($jsonresult);
$json2 = json_decode($jsonresult2);

// map locations to associative array
$addresses = array();
foreach($json2->locations as $currlocation) {
    $addresses[$currlocation->locationCode] = $currlocation->address;
}

// add addresses to events
$events = $json1->events;

function add_address(&$event, $key_not_used, $searcharray) {
    if(array_key_exists($event->location->locationCode, $searcharray)) {
        $event->address = $searcharray[$event->location->locationCode];
    }
}

array_walk($events, 'add_address', $addresses);

$merged_events = json_encode($events);
print_r($merged_events);
person Mike Brant    schedule 17.01.2014
comment
Нужно ли мне добавить ,true к функции json_decode? Я никогда не понимал точной разницы в возвращаемом объекте с/без true. - person Maxwell Donnelly; 17.01.2014
comment
@MaxwellDonnelly Параметр true заставит объекты объединяться в ассоциативные массивы. Лично я бы рекомендовал работать с объектами, так как когда вы копируете адресные объекты в события, вы на самом деле копируете только указатель на расположение объекта в памяти, так что это лучше с точки зрения управления памятью. В этом случае я также думаю, что объект более репрезентативен для того, с чем вы работаете в реальном мире. Вы работаете с адресами с дискретными свойствами (адресные строки, город, штат и т. д.) и событиями со своими свойствами. - person Mike Brant; 17.01.2014
comment
Ваш код меня ОЧЕНЬ близко. Было несколько синтаксических ошибок, которые мне пришлось исправлять (отсутствовала пара закрывающих скобок) и немного по-другому обращаться к объектам. В итоге я написал функцию array_walk вне самой функции array_walk, и мне пришлось переименовать несколько переменных. Мой готовый рабочий код добавлен к вашему ответу. - person Maxwell Donnelly; 18.01.2014