#php #arrays #grouping
#php #массивы #группировка
Вопрос:
У меня есть этот массив:
Array
(
[0] => Array
(
[id]=>1
[account_id] => 1
[object_id] => 43
[object_type] => PHOTO
[action_type] => UPLOAD_PHOTO
)
[1] => Array
(
[id] => 1
[account_id] => 1
[object_id] => 42
[object_type] => PHOTO
[action_type] => UPLOAD_PHOTO
)
[2] => Array
(
[id] => 1
[account_id] => 1
[object_id] => 41
[object_type] => PHOTO
[action_type] => UPLOAD_PHOTO
)
[3] => Array
(
[id] => 2
[account_id] => 2
[object_id] => 1
[object_type] => USER
[action_type] => FOLLOW_USER
)
[4] => Array
(
[id] => 1
[account_id] => 1
[object_id] => 2
[object_type] => USER
[action_type] => FOLLOW_USER
)
[5] => Array
(
[id] => 1
[account_id] => 1
[object_id] => 1
[object_type] => PHOTO
[action_type] => UPLOAD_PHOTO
)
)
Теперь я хочу сгруппировать элементы с одинаковым значением (например UPLOAD_PHOTO
) по идентификатору в качестве первичного ключа и action_type в качестве вторичного ключа, например:
Array
(
[0] => Array(
[id] => 1
[account_id] => 1
[actions] => array(
[1] => array(
[object_id] => 42
[object_type] => PHOTO
[action_type] => UPLOAD_PHOTO
)
[2] => array(
[object_id] => 43
[object_type] => PHOTO
[action_type] => UPLOAD_PHOTO
)
)
)
[2] => Array
(
[id] => 1
[account_id] => 1
[actions] = array(
[0] => Array
(
[object_id] => 3
[object_type] => USER
[action_type] => FOLLOW_USER
)
[1] => Array
(
[object_id] => 4
[object_type] => USER
[action_type] => FOLLOW_USER
)
)
)
)
Я пробовал некоторые решения, но безуспешно.
Комментарии:
1. Должен ли в первом элементе входного массива отсутствовать
[id]
атрибут?2. @MrTrick: да, моя ошибка, извините.
Ответ №1:
При построении вашего выходного массива вы захотите использовать значимые ключи массива. Таким образом, вы можете найти элемент out, к которому необходимо добавить элемент in:
$in = (...your array...);
$out = array();
foreach($in as $element) {
$id = $element['id'];
//If that id hasn't been seen yet, create the out element.
if (!isset($out[$id])) {
$out[$id] = array(
'id'=>$element['id'],
'account_id' => $element['account_id'],
'actions' => array()
);
}
//Add that action to the out element
$out[$id]['actions'][] = array(
'object_id' => $element['object_id'],
'object_type' => $element['object_type'],
'action_type' => $element['action_type']
);
}
Я не уверен, почему ваши входные элементы имеют разные поля… Если это желаемая функция, где один набор возможных полей принадлежит группе идентификаторов, а другой набор принадлежит действию, вы можете сделать это вместо этого (немного менее читаемый, но более гибкий):
$in = (...your array...);
$out = array();
//These define which fields from an
//input element belong to the id,
//and which to the action.
$id_fields = array_flip(array('id','account_id','object_user_id');
$action_fields = array_flip(array('object_id','object_type','action_type');
foreach($in as $element) {
$id = $element['id'];
//If that id hasn't been seen yet, create the out element.
if (!isset($out[$id])) {
$out[$id] = array_intersect_key($element, $id_fields);
$out[$id]['actions'] = array();
}
//Add that action to the out element
$out[$id]['actions'][] = array_intersect_key($element, $action_fields);
}
Это лучшее решение, если входные элементы могут быть разными, потому что, если ожидаемое поле (отличное от 'id'
) отсутствует, скрипт легко справится с этим.