PHP - Add new object to every array of objects - php

Consider this array of objects in PHP:
array:2 [
0 => array:4 [
"Row_Id" => 256
"Start_Date" => "2020-05-16"
"account_code" => ""
"caller_number" => "452"
]
1 => array:4 [
"Row_Id" => 257
"Start_Date" => "2020-05-16"
"account_code" => ""
"caller_number" => "42"
]
2 => array:4 [
"Row_Id" => 258
"Start_Date" => "2020-05-16"
"account_code" => ""
"caller_number" => "428"
]
]
I want to add "callee_number:100" in every array so my output should look like these:
array:2 [
0 => array:5 [
"Row_Id" => 256
"Start_Date" => "2020-05-16"
"account_code" => ""
"caller_number" => "452"
"callee_number" => "100"
]
1 => array:5 [
"Row_Id" => 257
"Start_Date" => "2020-05-16"
"account_code" => ""
"caller_number" => "42"
"callee_number" => "100"
]
2 => array:5 [
"Row_Id" => 258
"Start_Date" => "2020-05-16"
"account_code" => ""
"caller_number" => "428"
"callee_number" => "100"
]
]
I have taken the above input array in $get variable. Now I am calling array_push to append callee_number to every array:
array_push($get,[
'callee_number':'100'
]);
Also tried using array_merge but callee_number is not getting appended. How can I achieve that ?

Given the following array:
$array = [
[
"Row_Id" => 256,
"Start_Date" => "2020-05-16",
"account_code" => "",
"caller_number" => "452",
],
[
"Row_Id" => 257,
"Start_Date" => "2020-05-16",
"account_code" => "",
"caller_number" => "42",
],
[
"Row_Id" => 258,
"Start_Date" => "2020-05-16",
"account_code" => "",
"caller_number" => "428",
],
];
Native PHP
$array = array_map(function ($item) { return $item + ['callee_number' => 100]; }, $array);
Using collections
$array = collect($array)->map(function ($item) { return $item + ['callee_number' => 100]; })->toArray();
Using PHP 7.4 shorthands
$array = array_map(fn($item) => $item + ['callee_number' => 100], $array);
// Or
$array = collect($array)->map(fn($item) => $item + ['callee_number' => 100])->toArray();

To add or modify an element in each sub-array you would do this:
foreach ($get as &$g) {
$g["callee_number"] = 100;
}
Or this:
for ($c = 0; $c < count($get); $c++) {
$get[$c]["callee_number"] = 100;
}

Related

recursive function transform nested array

Im my laravel project I have this nested array that needs to be updated (transformed - for the frontend):
array:2 [
0 => array:3 [
"entity_id" => 931
"entity" => "user"
"children" => array:2 [
0 => array:2 [
"entity_id" => 5
"entity" => "location"
]
1 => array:2 [
"entity_id" => 932
"entity" => "user"
]
]
]
1 => array:2 [
"entity_id" => 486
"entity" => "user"
]
]
EXPECTED ARRAY:
array:2 [
0 => array:4 [
"id" => 931
"text" => "Test User 1"
"type" => "user"
"children" => array:2 [
0 => array:3 [
"id" => 5
"text" => "Location 1"
"type" => "location"
]
1 => array:3 [
"id" => 932
"text" => "Test User 2"
"type" => "user"
]
]
]
1 => array:3 [
"id" => 486
"text" => "Test User 3"
"type" => "user"
]
]
I have created a recursive function for this job
public function getNewStructure($tree, &$output) {
foreach($tree as $data) {
$output[] = array(
'id' => $data['entity_id'],
'text' => $data['user'] === 'user' ? User::find($data['entity_id'])->name : Location::find($data['entity_id'])->name,
'type' => $data['entity']
);
$this->getNewStructure($data['children'] ?? [], $output);
}
return $output;
}
but it not returns as expected:
array:4 [
0 => array:3 [
"id" => 931
"text" => "Test User 1"
"type" => "user"
]
0 => array:3 [
"id" => 5
"text" => "Location 1"
"type" => "location"
]
1 => array:3 [
"id" => 932
"text" => "Test User 2"
"type" => "user"
]
1 => array:3 [
"id" => 486
"text" => "Test User 3"
"type" => "user"
]
]
How can I add the children to the $output array in the recursive function ???
I have tried by adding the children key:
$this->getNewStructure($data['children'] ?? [], $output['children']);
as when iterating again it will push the current array in the right place.... but is not working...
I fixed
public function getNewStructure($tree, &$output) {
foreach($tree as $data) {
$element = array(
'id' => $data['entity_id'],
'text' => $data['user'] === 'user' ? User::find($data['entity_id'])->name : Location::find($data['entity_id'])->name,
'type' => $data['entity']
);
if(is_array($data['children']) && count($data['children']) > 0) {
$element['children'] = $this->getNewStructure($data['children'], $element['children']);
}
$output[] = $element;
}
return $output;
}

Not able to group inner array of the multi-dimensional array

I have an array like this & I need to group an array based on value.
array:3 [
0 => array:5 [
"id" => 1
"maxView" => 0
"maxClick" => 20
"companyName" => "Project A"
"email" => "user1#email.com"
]
1 => array:5 [
"id" => 1
"maxView" => 0
"maxClick" => 20
"companyName" => "Project A"
"email" => "user2#email.com"
]
2 => array:5 [
"id" => 1
"maxView" => 0
"maxClick" => 20
"companyName" => "Project A"
"email" => "user3#email.com"
]
3 => array:5 [
"id" => 1
"maxView" => 0
"maxClick" => 20
"companyName" => "Project B"
"email" => "user1#email.com"
]
4 => array:5 [
"id" => 1
"maxView" => 0
"maxClick" => 20
"companyName" => "Project B"
"email" => "user6#email.com"
]
]
So far, I have following lines of codes. This is grouping my array based on fieldName = companyName But I am not able to add emails belonging to companyname under an array.
foreach ($records as $record) {
if (!array_key_exists($record[$fieldName], $groupedArray)) {
$groupedArray[$record[$fieldName]] = [];
}
$groupedArray[$record[$fieldName]] = $record;
$groupedArray[$record[$fieldName]]['email'] = [];
if (!in_array($record['email'], $groupedArray[$record[$fieldName]]['email'], true)) {
$groupedArray[$record[$fieldName]]['email'][] = $record['email'];
}
}
My code is adding only last email to the array.
"Project A" => [
....
"email" => array:1 [
0 => "user3#email.com"
]
Can anybody help me what I am missing here ?

Php Recursivity: Convert a multidimensional associative array into an array that contains each level of data

I am looking for the best way to convert a multidimensional associative array into a new array, where each row is the concatenation of each column ex :
$datas[] = [
"id" => "1000",
"parent" => "0",
"level" => "1",
"children" => [
[
"id" => "1001",
"parent" => "1000",
"level" => "2",
"children" => [
[
"id" => "1002",
"parent" => "1001",
"level" => "3",
"children" => [
[
"id" => "1003",
"parent" => "1002",
"niveau" => "4",
],
[
"id" => "1004",
"parent" => "1002",
"niveau" => "4",
],
[
"id" => "1005",
"parent" => "1002",
"niveau" => "4",
]
]
],
[
]
]
],
[
"id" => "1006",
"parent" => "1000",
"level" => "2"
]
],
[
"id" => "1007",
"parent" => "0",
"level" => "1"
]
];
Here's my method :
public function recursData(array $datas, &$str ="", &$row =[], int $level = 0)
{
$level++;
foreach ($datas as $data) {
foreach($data as $key => $d) {
if (is_array($d)) {
$this->recursData($d, $str, $row,$level);
} else {
$str.= "{$level}_{$key}_{$d}|";
if ($key == "parent") {
$row[] = $str;
}
}
}
}
return $row;
}
Output (not what i'm looking for) :
array:8 [
0 => "1_id_1000|1_parent_0|"
1 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|"
2 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|"
3 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1003|4_parent_1002|"
4 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1003|4_parent_1002|4_id_1004|4_parent_1002|"
5 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1003|4_parent_1002|4_id_1004|4_parent_1002|4_id_1005|4_parent_1002|"
6 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1003|4_parent_1002|4_id_1004|4_parent_1002|4_id_1005|4_parent_1002|2_id_1006|2_parent_1000|"
7 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1003|4_parent_1002|4_id_1004|4_parent_1002|4_id_1005|4_parent_1002|2_id_1006|2_parent_1000|1_id_1007|1_parent_0|"
]
The output i'm looking for:
array:8 [
0 => "1_id_1000|1_parent_0"
1 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000"
2 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001"
3 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1003|3_parent_1002"
4 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1004|3_parent_1002"
5 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1005|3_parent_1002"
6 => "1_id_1000|1_parent_0|2_id_1006|2_parent_1000"
7 => "1_id_1007|1_parent_0"
]
I'm stuck to finish this properly, I tried lot of things, but can't understand what to do obtain what I want to resolve this. Hope someone could help :)

re-index array and add totals

I'm trying to figure out how to restructure an array and total values by given keys. I currently have an array called $data that is returning this result:
Bill => array:3 [▼
"01" => array:6 [▼
"Food " => array:2 [▶]
hamburger=>array:[
sales=> 210.00
purchases=>200.00
]
burrito=>array:[
sales=> 100.00
purchases=>40.00
]
"Drink " => array:2 [▶]
coke=>array:[
sales=> 210.00
purchases=>200.00
]
pepsi=>array:[
sales=> 100.00
purchases=>40.00
]
"total" => array:7 [▶]
sales=>620.00
purchases=>480.00
]
]
Ted => array:3 [▼
"01" => array:6 [▼
"Food " => array:2 [▶]
hamburger=>array:[
sales=> 110.00
purchases=>100.00
]
burrito=>array:[
sales=> 120.00
purchases=>40.00
]
"Drink " => array:2 [▶]
coke=>array:[
sales=> 110.00
purchases=>100.00
]
pepsi=>array:[
sales=> 120.00
purchases=>40.00
]
"total" => array:7 [▶]
sales=>460.00
purchases=>280.00
]
]
My issue is that I need to fit this into a laravel blade that is not concerned with bill or ted, but rather totals for everyone. Where the existing keys are "Bill" and "Ted", I would need the new structure to actually be identified by the "01", but I want to total all of the categories within that level. So I would be hoping to get results like this:
"01" =>[▼
"Food " => array:2 [▶]
hamburger=>array:[
sales=> 320.00
purchases=>300.00
]
burrito=>array:[
sales=> 220.00
purchases=>140.00
]
"Drink " => array:2 [▶]
coke=>array:[
sales=> 320.00
purchases=>300.00
]
pepsi=>array:[
sales=> 220.00
purchases=>80.00
]
"total" => array:7 [▶]
sales=>1080.00
purchases=>760.00
]
I can easily loop on this like:
foreach($data as $key=> $value){
foreach($value as $categoryNumber => $categories){
foreach($categories as $categoryDetails => $details){
}
}
}
But I'm completely stuck as to how to re-structure this and total by the new indices
I am not sure how you arrived at the above dd();, I am sure there is a better way of collecting these totals prior to arriving here. But now that you are here (say, you received this via an API or whatever), this would make the totals as you mentioned:
$result = [];
foreach ($input as $i) {
foreach ($i as $group => $n) {
if (!array_key_exists($group, $result)) $result[$group] = [];
foreach ($n as $category_name => $category) {
if (!array_key_exists($category_name, $result[$group])) $result[$group][$category_name] = [];
foreach ($category as $item_name => $item) {
if (!array_key_exists($item_name, $result[$group][$category_name])) {
$result[$group][$category_name][$item_name] = $item;
} else {
foreach ($item as $purpose => $dollars) {
$result[$group][$category_name][$item_name][$purpose] += $dollars;
}
}
}
}
}
}
In each step, I am checking if the array key exists, and if not, creating it. If you ignore those array_key_exists() checks, you'll see that I am simply copying the contents over and summing where necessary.
You do something like this...
<?php
$data = [
'Bill' => [
"01" => [
"Food" => [
'hamburger' => [
'sales' => 210.00,
'purchases' => 200.00,
],
'burrito' => [
'sales' => 100.00,
'purchases' => 40.00,
],
],
"Drink" => [
'coke' => [
'sales' => 210.00,
'purchases' => 200.00,
],
'pepsi' => [
'sales' => 100.00,
'purchases' => 40.00,
],
],
"total" => [
'sales' => 620.00,
'purchases' => 480.00,
],
]
],
'Ted' => [
"01" => [
"Food" => [
'hamburger' => [
'sales' => 110.00,
'purchases' => 100.00,
],
'burrito' => [
'sales' => 120.00,
'purchases' => 40.00,
],
],
"Drink" => [
'coke' => [
'sales' => 110.00,
'purchases' => 100.00,
],
'pepsi' => [
'sales' => 120.00,
'purchases' => 40.00,
],
],
"total" => [
'sales' => 460.00,
'purchases' => 280.00,
],
]
]
];
$finalResults = [];
foreach ($data as $userName => $bills) {
foreach ($bills as $billIndex => $billParts) {
if (!array_key_exists($billIndex, $finalResults)) {
$finalResults[$billIndex] = [
'total' => [
'sales' => 0,
'purchases' => 0,
]
];
}
foreach ($billParts as $partIndex => $details) {
if (!array_key_exists($partIndex, $finalResults[$billIndex])) {
$finalResults[$billIndex][$partIndex] = [];
}
if ($partIndex !== 'total') {
foreach ($details as $productCode => $productData) {
if (!array_key_exists($productCode, $finalResults[$billIndex][$partIndex])) {
$finalResults[$billIndex][$partIndex][$productCode] = [
'sales' => 0,
'purchases' => 0,
];
}
$finalResults[$billIndex][$partIndex][$productCode]['sales'] += $productData['sales'];
$finalResults[$billIndex][$partIndex][$productCode]['purchases'] += $productData['purchases'];
}
} else {
$finalResults[$billIndex][$partIndex]['sales'] += $details['sales'];
$finalResults[$billIndex][$partIndex]['purchases'] += $details['purchases'];
}
}
}
}
print_r($finalResults);

How to fix recursion in php?

I try to iterate all parents/child in recursion:
foreach ($data as $k => $item) {
$data[$k]["children"] = $this->getChildren($all, $item);
}
And recursive function:
private function getChildren($list, $item)
{
$children = [];
if (is_array($item["children"])) {
foreach ($item["children"] as $k => $id) {
$children[] = $list[$id];
}
} else {
if (isset($list[$item["children"]])) {
$children[] = $list[$item["children"]];
}
}
return $children;
}
Problem is that I need to call getChildren inside getChildren for founded element $list[$id] to check if this element does contain array children.
I tried to call this:
$children[] = $this->getChildren($list, $list[$id]);
But it does not work.
I tried this way:
private function getChildren($list, $item)
{
$children = [];
if (is_array($item["children"]) && count($item["children"]) > 0) {
foreach ($item["children"] as $k => $id) {
return $this->getChildren($list, $list[$id]);
}
}
return $list[$id];
}
The array $all that I try to iterate by children:
array:12 [
"592d0b3bb3569e257208db81" => array:10 [
"_id" => MongoId {#266
+$id: "592d0b3bb3569e257208db81"
}
"name" => "Характеристики героя"
"default" => "data"
"visibility" => null
"type" => "2"
"value" => "data"
"prefix" => "data"
"type_value" => "object"
"children" => array:7 [
0 => "592d094eb3569eb07208db7e"
1 => "592d0961b3569ee17708db80"
2 => "592d0978b3569eb07108db7e"
3 => "592d0987b3569ead7108db91"
4 => "592d09a5b3569eae7108db81"
5 => "592d09c1b3569eae7208db82"
6 => "592d0ac3b3569eae7208db83"
]
"available" => "1"
]
"592d0ac3b3569eae7208db83" => array:10 [
"_id" => MongoId {#267
+$id: "592d0ac3b3569eae7208db83"
}
"name" => "Умения"
"default" => "skills"
"visibility" => null
"type" => "2"
"value" => "skills"
"prefix" => "skills"
"type_value" => "object"
"children" => array:4 [
0 => "592d094eb3569eb07208db7e"
1 => "592d0a1db3569ee17708db81"
2 => "592d0a2fb3569e257208db80"
3 => "592d0a58b3569ead7108db92"
]
"available" => "1"
]
"592d0a58b3569ead7108db92" => array:10 [
"_id" => MongoId {#268
+$id: "592d0a58b3569ead7108db92"
}
"name" => "Начальная прокачка"
"default" => "0"
"visibility" => null
"type" => "1"
"value" => "0"
"prefix" => "startPumping"
"type_value" => "integer"
"children" => []
"available" => "1"
]
"592d0a2fb3569e257208db80" => array:10 [
"_id" => MongoId {#269
+$id: "592d0a2fb3569e257208db80"
}
"name" => "Максимальная прокачка"
"default" => "0"
"visibility" => null
"type" => "1"
"value" => "0"
"prefix" => "maxPumping"
"type_value" => "integer"
"children" => []
"available" => "1"
]
"592d0a1db3569ee17708db81" => array:10 [
"_id" => MongoId {#270
+$id: "592d0a1db3569ee17708db81"
}
"name" => "Текущая прокачка"
"default" => "0"
"visibility" => null
"type" => "1"
"value" => "0"
"prefix" => "pumping"
"type_value" => "integer"
"children" => []
"available" => "1"
]
"592d09c1b3569eae7208db82" => array:10 [
"_id" => MongoId {#271
+$id: "592d09c1b3569eae7208db82"
}
"name" => "Свободных умений"
"default" => "0"
"visibility" => null
"type" => "1"
"value" => "0"
"prefix" => "freePumpingPoints"
"type_value" => "integer"
"children" => []
"available" => "1"
]
"592d09a5b3569eae7108db81" => array:10 [
"_id" => MongoId {#272
+$id: "592d09a5b3569eae7108db81"
}
"name" => "Требования"
"default" => "Что бы получить Этого персонажа, вам нужно заплатить миллион американских рублей и подарить нам почку"
"visibility" => null
"type" => "1"
"value" => "Что бы получить Этого персонажа, вам нужно заплатить миллион американских рублей и подарить нам почку"
"prefix" => "requirements"
"type_value" => "string"
"children" => []
"available" => "1"
]
"592d0987b3569ead7108db91" => array:10 [
"_id" => MongoId {#273
+$id: "592d0987b3569ead7108db91"
}
"name" => "Описание"
"default" => "Описание"
"visibility" => null
"type" => "1"
"value" => "Описание"
"prefix" => "description"
"type_value" => "string"
"children" => []
"available" => "1"
]
"592d0978b3569eb07108db7e" => array:10 [
"_id" => MongoId {#274
+$id: "592d0978b3569eb07108db7e"
}
"name" => "Название"
"default" => "Название"
"visibility" => null
"type" => "1"
"value" => "Название"
"prefix" => "name"
"type_value" => "string"
"children" => []
"available" => "1"
]
"592d0961b3569ee17708db80" => array:10 [
"_id" => MongoId {#275
+$id: "592d0961b3569ee17708db80"
}
"name" => "Уровень"
"default" => "0"
"visibility" => null
"type" => "1"
"value" => "0"
"prefix" => "level"
"type_value" => "integer"
"children" => []
"available" => "1"
]
"592d094eb3569eb07208db7e" => array:10 [
"_id" => MongoId {#276
+$id: "592d094eb3569eb07208db7e"
}
"name" => "Идентификатор"
"default" => "0"
"visibility" => null
"type" => "1"
"value" => "0"
"prefix" => "id"
"type_value" => "integer"
"children" => []
"available" => "1"
]
"592d0932b3569e277208db87" => array:10 [
"_id" => MongoId {#277
+$id: "592d0932b3569e277208db87"
}
"name" => "Сила отбития"
"default" => "0"
"visibility" => null
"type" => "1"
"value" => "0"
"prefix" => "hitForce"
"type_value" => "integer"
"children" => []
"available" => "1"
]
]"available" => "1"
]
]
My version of recursie:
private function getChildren($list, $item, $c)
{
if (is_array($item["children"])) {
foreach ($item["children"] as $k => $id) {
if(count($list[$id]["children"]) > 0){
$_id = (string)$list[$id]["_id"];
$c[][$_id] = $list[$id];
$c[][$_id]["children"] = $this->getChildren($list, $list[$id], $c);
} else {
$c[] = $list[$id];
}
}
}
return $c;
}
Calling:
foreach ($data as $k => $item) {
$data[$k]["children"] = $this->getChildren($all, $item, $c);
}
this is a quick example using a sampler array rather than your array, just to clarify and simplify the solution in a general context.
$data = [
0 => ['name' => 'b0', 'children' => [3,5]],
1 => ['name' => 'b1', 'children' => []],
2 => ['name' => 'b2', 'children' => [1]],
3 => ['name' => 'b3', 'children' => []],
4 => ['name' => 'b4', 'children' => []],
5 => ['name' => 'b5', 'children' => [4]],
];
function recursive($data, $childs)
{
$list = [];
foreach ($childs as $child) {
if (is_array($data[$child]['children'])) {
// storing the output of the recursive array in a tmp variable
$tmpArray['name'] = $data[$child]['name'];
$tmpArray['children'] = recursive($data, $data[$child]['children']);
} else {
$tmpArray = $data[$child];
}
$list[] = $tmpArray;
}
return $list;
}
foreach ($data as $key => $value) {
// Here we are going to check whether the array have inner childs or not , only to take in account the other empty elements
if (is_array($value['children']) && count($value['children']) > 0) {
$list[] = recursive($data, $value['children']);
} else {
$list[] = $value;
}
}
print_r($list);
here is a quick demo : https://eval.in/807433
P.S, the more data you will get, the more load & time you will get
maybe redesign your mongoDB document will be a good choice to avoid this, maybe

Categories