#php #arrays #object
Вопрос:
Мне трудно манипулировать массивом объектов в PHP. Мне нужно сгруппировать объекты по id
, подводя итоги points
.
Начальный массив объектов:
[
{
"id": "xx",
"points": 25
},
{
"id": "xx",
"points": 40
},
{
"id": "xy",
"points": 40
},
]
Что мне нужно:
[
{
"id": "xx",
"points": 65
},
{
"id": "xy",
"points": 40
},
]
Как фронтендер, я испытываю трудности с манипуляциями с объектами/массивами в PHP. Любая помощь будет очень признательна!
Ответ №1:
- Анализировать JSON как объект
- Агрегированные Данные
- Верните как JSON
$json = <<<'_JSON'
[
{
"id": "xx",
"points": 25
},
{
"id": "xx",
"points": 40
},
{
"id": "xy",
"points": 40
}
]
_JSON;
$aggregate = [];
foreach(json_decode($json) as $data) {
if(!isset($aggregate[$data->id])) $aggregate[$data->id] = 0;
$aggregate[$data->id] = $data->points;
}
$output = [];
foreach($aggregate as $id => $points) {
$output[] = ['id' => $id, 'points' => $points];
}
echo json_encode($output);
[{"id":"xx","points":65},{"id":"xy","points":40}]
Комментарии:
1. Мне придется прочитать некоторую документацию по синтаксическому анализу/кодированию json / объектов. Большое спасибо.
Ответ №2:
Вы можете использовать array_reduce
встроенную функцию для выполнения этой работы. Кроме того, при циклическом просмотре массива объекта (обратный вызов) вы должны проверить, имеет ли результирующий массив идентификатор текущего элемента, чтобы убедиться, нужно ли вам добавить элемент в результирующий массив или сделать сумму атрибутов точек.
Вот пример:
// a dummy class just to replicate the objects with ID and points attributes
class Dummy
{
public $id;
public $points;
public function __construct($id, $points)
{
$this->id = $id;
$this->points = $points;
}
}
// the array of objects
$arr = [new Dummy('xx', 25), new Dummy('xx', 40), new Dummy('xy', 40)];
// loop through the array
$res = array_reduce($arr, function($carry, $item) {
// holds the index of the object that has the same ID on the resulting array, if it stays NULL means it should add $item to the result array, otherwise calculate the sum of points attributes
$idx = null;
// trying to find the object that has the same id as the current item
foreach($carry as $k => $v)
if($v->id == $item->id) {
$idx = $k;
break;
}
// if nothing found, add $item to the result array, otherwise sum the points attributes
$idx === null ? $carry[] = $item:$carry[$idx]->points = $item->points;
// return the result array for the next iteration
return $carry;
}, []);
Это приведет к чему-то вроде этого:
array(2) {
[0]=>
object(Dummy)#1 (2) {
["id"]=>
string(2) "xx"
["points"]=>
int(65)
}
[1]=>
object(Dummy)#3 (2) {
["id"]=>
string(2) "xy"
["points"]=>
int(40)
}
}
Надеюсь, это поможет, не стесняйтесь обращаться за дополнительной помощью.
Комментарии:
1. Спасибо за очень подробное объяснение.
Ответ №3:
я надеюсь, что этот ответ поможет вам сначала я изменю объекты в массив и снова верну результат в массив
$values =[
[
"id"=> "xx",
"points"=> 25
],
[
"id"=> "xx",
"points"=> 40
],
[
"id"=> "xy",
"points"=> 40
],
];
$res = array();
foreach($values as $vals){
if(array_key_exists($vals['id'],$res)){
$res[$vals['id']]['points'] = $vals['points'];
$res[$vals['id']]['id'] = $vals['id'];
}
else{
$res[$vals['id']] = $vals;
}
}
$result = array();
foreach ($res as $item){
$result[] = (object) $item;
}
Комментарии:
1. Это отлично работает, большое вам спасибо!!
Ответ №4:
Давайте используем вспомогательную переменную под названием $map
:
$map = [];
Создайте свою карту:
foreach ($input => $item) {
if (!isset($map[$item["id"]])) $map[$item["id"]] = 0;
$map[$item["id"]] = $item["points"];
}
Теперь давайте построим вывод:
$output = [];
foreach ($map as $key => $value) {
$output[] = (object)["id" => $key, "points" => $value];
}