php how to grouping by id - php

I'm very new in PHP. I'm doing with the array data structure. Currently, I got two result which is the same ID but different details. I need to combine the details based on the ID.
This is my array result
array:2 [
0 => array:13 [
"id" => "1"
"date" => "01-02-2019"
"order" => array:1 [
0 => array:2 [
"code" => "F001"
"name" => "fish"
]
]
]
1 => array:13 [
"id" => "1"
"date" => "01-02-2019"
"order" => array:1 [
0 => array:2 [
"code" => "F002"
"name" => "chicken"
]
]
]
]
This is my expected result
array:1 [
0 => array:13 [
"id" => "1"
"date" => "01-02-2019"
"order" => array:2 [
0 => array:2 [
"code" => "F001"
"name" => "fish"
]
1 => array:2 [
"code" => "F002"
"name" => "chicken"
]
]
]
]
I'm trying to insert the order array if there have the same id
This is my code
public function order($value)
{
$group_id = [];
$groupItem = [];
foreach ($value as $item) {
$item['date'] = date('Y-m-d',strtotime($item['date']));
$groupItem = $item['order'][] = [
'id' => $item['id'],
'name' => $item['name'],
];
$group_id[$item['id']][]= $groupItem;
}
}
Result
array:1 [
"1" => array:1 [
0 => array:2 [
"code" => "F001"
"name" => "fish"
]
1 => array:2 [
"code" => "F002"
"name" => "chicken"
]
]
]
As you can see, I grouped the order but the date and id were missing.

Here is a working order function:
function order($input) {
$output = array();
foreach($input as $item) {
if (!isset($output[$item['id']])) {
$output[$item['id']] = array(
"id" => $item["id"],
"date" => $item["date"],
"order" => array()
);
}
$output[$item['id']]['order'][] = $item['order'];
}
return array_values($output);
}
INPUT:
array(
array(
"id" => "1",
"date" => "01-02-2019",
"order" => array(
array(
"code" => "F001",
"name" => "fish"
)
)
),
array(
"id" => "1",
"date" => "01-02-2019",
"order" => array(
array(
"code" => "F002",
"name" => "chicken"
)
)
)
);
OUTPUT:
array(
array(
"id"=> "1",
"date"=> "01-02-2019",
"order"=> array(
array(
array(
"code"=> "F001",
"name"=> "fish"
)
),
array(
array(
"code"=> "F002",
"name"=> "chicken"
)
)
)
)
)

Assign the proper data. Try -
foreach ($value as $item) {
$date = date('Y-m-d',strtotime($item['date']));
$id = $item['id'];
$group_id[$id]['id'] = $id;
$group_id[$id]['date'] = $date;
$group_id[$id]['order'][] = [
'id' => $item['id'],
'name' => $item['name'],
];
}

I would write something like this, if you need to account for multiple IDs:
$result = array_reduce( $input, function ( $result, $item ) {
$id = $item['id'];
if ( ! isset( $result[ $id ] ) ) { // We don't have an item yet.
$result[ $id ] = $item;
} else { // We have an item and need to add orders to it.
$result[ $id ]['order'] = array_merge( $result[ $id ]['order'], $item['order'] );
}
return $result;
}, [] );

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;
}

Check if the given value exist in another array?

I have an array with some values as below:
$array1 = [
0 => "year",
1 => "month"
];
I make a loop to this array and check if its value exist in following array.
array:3 [
0 => array:3 [
"name" => "year"
"mandatory" => true
"type" => "integer"
]
1 => array:3 [
"name" => "month"
"mandatory" => true
"type" => "integer"
]
2 => array:3 [
"name" => "id"
"mandatory" => false
"type" => "integer"
]
]
If if exists then I have to return array something like this
array[
"year" => [
"mandatory" => true
"type" => "integer"
],
"month" => [
"mandatory" => true
"type" => "integer"
],
]
This is the code so far I have tried.
$keys = array_keys($params);
$fields = $config["fields"];
$finalArr = array();
foreach($keys as $key) {
if(in_array($key, array_column($fields, "name"))) {
$finalArr[$key] = array();
}
$finalArr[$key][] = $fields;
}
But this returns all the records.
Can anybody help me.
Iterate over your $fields and check if field's name exists in $keys:
foreach ($fields as $field) {
if (in_array($field['name'], $keys)) {
$finalArr[$field['name']] = $field;
}
}

Removed array grouped key

Is it possible to remove the key after data is grouped? Now I'm working with the csv file import function. I have two rows of data with the same student but different books because I want to group the books based on the student ID.
Code
foreach ($book as $item) {
$item['books'] = [
'number' => $item['number'],
'description' => $item['description'],
];
if (!isset($group_by[$item['student_id']])) {
$group_by[$item['student_id']] = array(
'student_id' => $item['student_id'],
'name' => $item['name'],
);
}
$group_by[$item['student_id']]['books'][] = $item['books'];
}
This is my grouping function, it worked perfectly as expected but the data structure is not matched to my system
Result is here
array:1 [
"ST001" => array:9 [
"student_id" => "ST001"
"name" => "joe"
"books" => array:2 [
0 => array:2 [
"number" => "1"
"description" => "The magic"
]
1 => array:2 [
"number" => "2"
"description" => "Forest in norway"
]
]
]
]
Expect result
array:9 [
"student_id" => "ST001"
"name" => "joe"
"books" => array:2 [
0 => array:2 [
"number" => "1"
"description" => "The magic"
]
1 => array:2 [
"number" => "2"
"description" => "Forest in norway"
]
]
]
I have no idea how to remove the St001 array. I did tried this $group_by[] = array( but the books data will be break out of data structure.
Assign the inner array to another array.
$array = $array['ST001'];
It will help out here
foreach($book as $item)
{
$item['books'] = ['number' => $item['number'], 'description' => $item['description'], ];
if (!isset($group_by[$item['student_id']]))
{
$group_by[$item['student_id']] = array(
'student_id' => $item['student_id'],
'name' => $item['name'],
);
}
$group_by[$item['student_id']]['books'][] = $item['books'];
}
// remove key and get only value as you want
print_r(array_values($group_by));

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

php iterate multidimesional array with array_map

i have an array as below :
array:4 [
"tag" => "form"
"attr" => array:1 [
"class" => array:1 [
0 => "form-horizontal"
]
]
"text" => " "
"child" => array:1 [
0 => array:3 [
"tag" => "fieldset"
"text" => " "
"child" => array:1 [
0 => array:2 [
"tag" => "input"
"text" => "input name"
]
]
]
]
]
id like to recreate a new array as below
array[
0 => array[
"input" => "something",
"value" => "somevalue"
],
0 => array[
"input" => "something",
"value" => "somevalue"
]
]
if "tag" => "input"
currently am using below code , laravel based :
public function AjaxData(Request $request)
{
//
$array = $request->json;
debug($array);
$array2 = array_map(array($this, 'sanitize'), $test1 );
debug($array2);
return response()->json(['name' => $array['tag'] ]);
}
private function sanitize($value)
{
return $value['tag'];
}

Categories