I'm stuck on this problem and I hope someone can help me on that. I have an array which I want to group by a specific key. The only problem is that I want to have a new array whenever the value of the key changes during the loop. Here is an example of the array.
Array
(
[0] => Array
(
[id] => 972
[user_id] => 2
[user_field_48] => 1
[project] => 100 — NLO
[duration] => 1:00
[grouped_by] => 1
)
[1] => Array
(
[id] => 644
[user_id] => 2
[user_field_48] => 4
[project] => 123 — QHV
[duration] => 15:00
[grouped_by] => 4
)
[2] => Array
(
[id] => 631
[user_id] => 2
[user_field_48] => 4
[project] =>
[duration] => -5:00
[grouped_by] => 4
)
[3] => Array
(
[id] => 630
[user_id] => 2
[user_field_48] => 1
[project] =>
[duration] => 22:00
[grouped_by] => 1
)
[4] => Array
(
[id] => 971
[user_id] => 2
[user_field_48] => 1
[project] => 100 — NLO
[duration] => 1:00
[grouped_by] => 1
)
[5] => Array
(
[id] => 973
[user_id] => 2
[user_field_48] => 1
[project] => 100 — NLO
[duration] => 1:00
[grouped_by] => 1
)
[6] => Array
(
[id] => 974
[user_id] => 2
[user_field_48] => 1
[project] => 100 — NLO
[duration] => 1:00
[grouped_by] => 1
)
)
I did
foreach($report_items as $item)
{
$groupedItems[$item['grouped_by']][] = $item;
}
and I got
Array
(
[1] => Array
(
[0] => Array
(
[id] => 972
[user_id] => 2
[user_field_48] => 1
[project] => 100 — NLO
[duration] => 1:00
[grouped_by] => 1
)
[1] => Array
(
[id] => 630
[user_id] => 2
[user_field_48] => 1
[project] =>
[duration] => 22:00
[grouped_by] => 1
)
[2] => Array
(
[id] => 971
[user_id] => 2
[user_field_48] => 1
[project] => 100 — NLO
[duration] => 1:00
[grouped_by] => 1
)
[3] => Array
(
[id] => 973
[user_id] => 2
[user_field_48] => 1
[project] => 100 — NLO
[duration] => 1:00
[grouped_by] => 1
)
[4] => Array
(
[id] => 974
[user_id] => 2
[user_field_48] => 1
[project] => 100 — NLO
[duration] => 1:00
[grouped_by] => 1
)
)
[4] => Array
(
[0] => Array
(
[id] => 644
[user_id] => 2
[user_field_48] => 4
[project] => 123 — QHV
[duration] => 15:00
[grouped_by] => 4
)
[1] => Array
(
[id] => 631
[user_id] => 2
[user_field_48] => 4
[project] =>
[duration] => -5:00
[grouped_by] => 4
)
)
)
What I'm actually looking for is something like this, where the arrays are separated during the loop and a suffix is added to the key whenever the value changes.
Array
(
[1.1] => Array
(
[0] => Array
(
[id] => 972
[user_id] => 2
[user_field_48] => 1
[project] => 100 — NLO
[duration] => 1:00
[grouped_by] => 1
)
)
[4.1] => Array
(
[0] => Array
(
[id] => 644
[user_id] => 2
[user_field_48] => 4
[project] => 123 — QHV
[duration] => 15:00
[grouped_by] => 4
)
[1] => Array
(
[id] => 631
[user_id] => 2
[user_field_48] => 4
[project] =>
[duration] => -5:00
[grouped_by] => 4
)
)
[1.2] => Array
(
[0] => Array
(
[id] => 630
[user_id] => 2
[user_field_48] => 1
[project] =>
[duration] => 22:00
[grouped_by] => 1
)
[1] => Array
(
[id] => 971
[user_id] => 2
[user_field_48] => 1
[project] => 100 — NLO
[duration] => 1:00
[grouped_by] => 1
)
[2] => Array
(
[id] => 973
[user_id] => 2
[user_field_48] => 1
[project] => 100 — NLO
[duration] => 1:00
[grouped_by] => 1
)
[3] => Array
(
[id] => 974
[user_id] => 2
[user_field_48] => 1
[project] => 100 — NLO
[duration] => 1:00
[grouped_by] => 1
)
)
)
I'm not really aware of a simple way to solve this, so I would appreciate any help. Thank you!
CodePudding user response:
Not going to bother to recreate your full array here, I am using a reduced version with just the id and the grouped_by value, but the principle is of course exactly the same if you do it with your "full" array.
I am using a counter array to keep track of which "iteration" of a specific group we are currently dealing with. In classic control break implementation logic, I am comparing the grouped_by of the current record, with that of the previous one - if those differ, then the counter for this grouped_by value has to be incremented by 1. And then, I am simply creating the array key to use, by combining the grouped_by value, and the current count for it.
$data = [['id' => 972, 'grouped_by' => 1], ['id' => 664, 'grouped_by' => 4], ['id' => 631, 'grouped_by' => 4], ['id' => 630, 'grouped_by' => 1], ['id' => 971, 'grouped_by' => 1], ['id' => 973, 'grouped_by' => 1], ['id' => 974, 'grouped_by' => 1]];
$grouped_result = $grouped_by_counts = [];
$previous_grouped_by = null; // a value that will never occur in the data
foreach($data as $datum) {
if($datum['grouped_by'] !== $previous_grouped_by) {
$grouped_by_counts[$datum['grouped_by']] =
isset($grouped_by_counts[$datum['grouped_by']]) ?
$grouped_by_counts[$datum['grouped_by']] 1 : 1;
}
$grouped_result[
$datum['grouped_by'].'.'.$grouped_by_counts[$datum['grouped_by']]
][] = $datum;
$previous_grouped_by = $datum['grouped_by'];
}
print_r($grouped_result);
Live example: https://3v4l.org/odtie