I need to append certain values of Second array to the first array
I.e.,
In the First Array i create two elements such as name and price and get the values from Second Array and give it to first array
Here is my First Array
[
{
"id": 8,
"user_id": 21,
"category_id": 1,
"juice_id": 2,
"count": "100",
"status": "1",
"created_at": "2016-02-23 07:12:14",
"updated_at": "2016-02-23 07:12:14"
},
{
"id": 9,
"user_id": 21,
"category_id": 1,
"juice_id": 1,
"count": "100",
"status": "1",
"created_at": "2016-02-23 07:15:47",
"updated_at": "2016-02-23 07:15:47"
}
]
And the Second array is
{
"1": {
"id": 2,
"store_id": 1,
"category_id": 1,
"name": "Cashew Butter Baby",
"image": "http://greenhoppingbucket.s3.amazonaws.com/juice/1455719144rebV3iRUlj.png",
"description": "Cashew, Butter and Milk",
"price": "12.00",
"status": 1,
"created_at": "2016-02-17 19:56:11",
"updated_at": "2016-02-17 19:56:11"
},
"2": {
"id": 1,
"store_id": 1,
"category_id": 1,
"name": "Kalekolada",
"image": "http://greenhoppingbucket.s3.amazonaws.com/juice/1455719105WAVB3SGxT7.png",
"description": "Pulp of Kale",
"price": "10.00",
"status": 1,
"created_at": "2016-02-17 19:55:34",
"updated_at": "2016-02-17 19:55:34"
}
}
My Expected result is
[
{
"id": 8,
"user_id": 21,
"category_id": 1,
"juice_id": 2,
"count": "100",
"status": "1",
"created_at": "2016-02-23 07:12:14",
"updated_at": "2016-02-23 07:12:14"
"name": "Cashew Butter Baby",
"price": "12.00",
},
{
"id": 9,
"user_id": 21,
"category_id": 1,
"juice_id": 1,
"count": "100",
"status": "1",
"created_at": "2016-02-23 07:15:47",
"updated_at": "2016-02-23 07:15:47",
"name": "Kalekolada",
"price": "10.00",
}
]
I tried to do $newArray = array_merge($cartData, $juiceData);
But it is simply merging two arrays.
What is the mistake and how can i do that ?
Here's some code for merging those arrays. You should have a common index for them though (a different order may lead to unexpected behavior).
<?php
$a = array(
array(
"id" => 8,
"user_id" => 21,
"category_id" => 1,
"juice_id" => 2,
"count" => "100",
"status" => "1",
"created_at" => "2016-02-23 07:12:14",
"updated_at" => "2016-02-23 07:12:14"
),
array(
"id" => 9,
"user_id" => 21,
"category_id" => 1,
"juice_id" => 1,
"count" => "100",
"status" => "1",
"created_at" => "2016-02-23 07:15:47",
"updated_at" => "2016-02-23 07:15:47"
)
);
$b = array(
array(
"id" => 2,
"store_id" => 1,
"category_id" => 1,
"name" => "Cashew Butter Baby",
"image" => "http://greenhoppingbucket.s3.amazonaws.com/juice/1455719144rebV3iRUlj.png",
"description" => "Cashew, Butter and Milk",
"price" => "12.00",
"status" => 1,
"created_at" => "2016-02-17 19:56:11",
"updated_at" => "2016-02-17 19:56:11"
),
array(
"id" => 1,
"store_id" => 1,
"category_id" => 1,
"name" => "Kalekolada",
"image" => "http://greenhoppingbucket.s3.amazonaws.com/juice/1455719105WAVB3SGxT7.png",
"description" => "Pulp of Kale",
"price" => "10.00",
"status" => 1,
"created_at" => "2016-02-17 19:55:34",
"updated_at" => "2016-02-17 19:55:34"
)
);
// For this to work the arrays need to have the same string keys
// $merge = array_merge_recursive( $a, $b );
$merge = array();
foreach( $b as $key => $entry ) {
if( isset($a[$key]) ) {
$entry += $a[$key];
}
$merge[] = $entry;
}
var_dump( $merge );
EDIT:
New info in comments would give us something like:
$categories = array();
foreach( $b as &$entry ) {
$categories[$entry['id']] =& $entry;
}
$products = array();
foreach( $a as &$entry ) {
if( isset($categories[$entry['juice_id']]) ) {
$entry['category'] =& $categories[$entry['juice_id']];
}
$products[] =& $entry;
}
var_dump( $products );
No need to pass them by reference but should save some memory.
Related
I am working with php in laravel, in this case I have 2 collections of objects, one of them looks like this:
[
{
"id": 1,
"name": "product x",
"quantity": "100",
},
{
"id": 2,
"codProd": "product y",
"quantity": "200",
},
{
"id": 3,
"name": "product a.",
"quantity": "30",
}
]
and the other looks like this:
[
{
"reference": 1,
"quantity": "80",
},
{
"reference": 2,
"quantity": "50",
},
]
What I need is to keep the first collection but adding the value of the quantity key from the second collection, using the reference key as a relationship with the id of the first collection, the final result should look like this:
[
{
"id": 1,
"name": "product x",
"quantity": "180",
},
{
"id": 2,
"codProd": "product y",
"quantity": "250",
},
{
"id": 3,
"name": "product a.",
"quantity": "30",
}
]
so how can I do this?, any guide or help I am grateful
You can use a collection method for this, the map method:
$collection_one = collect([
[
'id' => 1,
'name' => 'product x',
'quantity' => 100,
],
[
'id' => 2,
'name' => 'product y',
'quantity' => 100,
],
[
'id' => 1,
'name' => 'product a.',
'quantity' => 30,
],
]);
$collection_two = collect([
[
'reference' => 1,
'quantity' => 80,
],
[
'reference' => 2,
'quantity' => 50,
],
]);
For you to get the collection what you want:
$collect = [];
$collect = $collection_one->map(function ($value_one) use ($collection_two) {
if ($search = $collection_two->firstWhere('reference', '=', $value_one['id'])) {
$value_one['quantity'] += $search['quantity'];
}
return $value_one;
});
Ready, that worked for me. :)
i have an Array like this:
[ [ "id": 1, "name": "Kategorie 1", "parent_id": null, [ "id": 2, "name": "Kategorie 1.1", "parent_id": 1, [ "id": 5, "name": "Kategorie 1.1.1", "parent_id": 2, [ "id": 11, "name": "Kategorie 1.1.1.1", "parent_id": 5, [] ], [ "id": 12, "name": "Kategorie 1.1.1.2", "parent_id": 5, [] ] , ........]
So this is a Category Hierachy like:
Category 1
Category 1.1
Category 1.2
Category 1.2.1
Category 1.2.1.1.
Category 2
Category 2.1.
Category 2.1.1.
Category 2.2
Category 2.3.
But the depth of the Categories is variable.
So is there a way to flat/merge the Array to:
[ [ "id": 1, "name": "Kategorie 1", "parent_id": null], [ "id": 2, "name": "Kategorie 1.1", "parent_id": 1], [ "id": 5, "name": "Kategorie 1.1.1", "parent_id": 2], [ "id": 11, "name": "Kategorie 1.1.1.1", "parent_id": 5], [ "id": 12, "name": "Kategorie 1.1.1.2", "parent_id": 5] ]
There you go:
<?php
$array = [
[
"id" => 1, "name" => "Kategorie 1", "parent_id" => null,
[
"id" => 2, "name" => "Kategorie 1.1", "parent_id" => 1,
[
"id" => 5, "name" => "Kategorie 1.1.1", "parent_id" => 2,
[
"id" => 11, "name" => "Kategorie 1.1.1.1", "parent_id" => 5, []
],
[
"id" => 12, "name" => "Kategorie 1.1.1.2", "parent_id" => 5, []
]
]
]
]
];
function flatMerge(array $array, array &$result = [])
{
$subResult = [];
foreach ($array as $key => $sub) {
if (is_array($sub)) {
flatMerge($sub, $result);
} else {
$subResult[$key] = $sub;
}
}
$result[] = $subResult;
return $result;
}
$result = flatMerge($array); // flat merge the array
var_dump($result);
$result = array_filter($result, static function (array $array) { // remove empty arrays
return !empty($array);
});
var_dump($result);
$result = array_values($result); // reset array keys
var_dump($result);
You can see the result of this code here: http://sandbox.onlinephpfunctions.com/code/b4eaddb4a52f5e9cf9a80644190e526613381c60
Supposing your array like this:
$arr = [
[
"id" => 1, "name" => "Kategorie 1", "parent_id" => null,
"children" => [
"id" => 2, "name" => "Kategorie 1.1", "parent_id" => 1,
"children" => [
"id" => 5, "name" => "Kategorie 1.1.1", "parent_id" => 2,
children => [
[ "id" => 11, "name" => "Kategorie 1.1.1.1", "parent_id" => 5, "children" => [] ],
[ "id" => 12, "name" => "Kategorie 1.1.1.2", "parent_id"=> 5, "children" => [] ]
]
]
]
]
];
The following function may work in your case, using recursion function:
function flatten(array $array) {
$branch = [];
foreach ($array as $item) {
$children = [];
if (isset($item["children"]) && is_array($item["children"])) {
$children = flatten($item["children"]);
unset($item["children"]);
}
$branch = array_merge($branch, [$item], $children);
}
return $branch;
}
i have an array like this with position disordered i want to order the position like 123 123 123 12
[{
"id": 1,
"name": "ASDAS",
"position": 1,
},
{
"id": 2,
"name": "ASDAS",
"position": 1,
},
{
"id": 3,
"name": "ASDAS",
"position": 3,
},
{
"id": 4,
"name": "ASDAS",
"position": 2,
},
{
"id": 5,
"name": "ASDAS",
"position": 2,
},
{
"id": 6,
"name": "ASDAS",
"position": 3,
},
{
"id": 7,
"name": "ASDAS",
"position": 2,
},
{
"id": 8,
"name": "ASDAS",
"position": 1,
}
]
i want the order like that
[{
"id": 1,
"name": "ASDAS",
"position": 1,
},
{
"id": 4,
"name": "ASDAS",
"position": 2,
},
{
"id": 3,
"name": "ASDAS",
"position": 3,
},
{
"id": 2,
"name": "ASDAS",
"position": 1,
},
{
"id": 5,
"name": "ASDAS",
"position": 2,
},
{
"id": 6,
"name": "ASDAS",
"position": 3,
},
{
"id": 8,
"name": "ASDAS",
"position": 1,
},
{
"id": 7,
"name": "ASDAS",
"position": 2,
}
]
The below should do the trick. I assume your data is an array of objects.
First I order the array by ID and then seperate the items by group. Finally, I merge all the groups 1 item at a time. There is probably a better way to acheive what you are after but thought this might be a good starting point.
This will adapt to the max position value. For example, if one of the data items has a position of 4 you would end up with a position order: 1234 123 123 123 12... etc
<?php
$input = [
(object)[
"id" => 1,
"name" => "ASDAS",
"position" => 1,
],
(object)[
"id" => 2,
"name" => "ASDAS",
"position" => 1,
],
(object)[
"id" => 3,
"name" => "ASDAS",
"position" => 3,
],
(object)[
"id" => 4,
"name" => "ASDAS",
"position" => 2,
],
(object)[
"id" => 5,
"name" => "ASDAS",
"position" => 2,
],
(object)[
"id" => 6,
"name" => "ASDAS",
"position" => 3,
],
(object)[
"id" => 7,
"name" => "ASDAS",
"position" => 2,
],
(object)[
"id" => 8,
"name" => "ASDAS",
"position" => 1,
]
];
// Sort array by ID
usort($input, function($a, $b) {
return $a->id <=> $b->id;
});
$groups = [];
foreach ($input as $item) {
// Create new group array
if (!array_key_exists($item->position, $groups)) {
$groups[$item->position] = [];
}
// Add item to group
$groups[$item->position][] = $item;
}
// Sort groups by position
ksort($groups);
// Merge groups 1 item at a time
function merge_groups(&$groups, &$target) {
foreach ($groups as $position => $group) {
if (!empty($group)) {
$target[] = array_shift($groups[$position]);
} else {
unset($groups[$position]);
}
}
if (!empty($groups)) {
merge_groups($groups, $target);
}
}
// Our final result array
$ouput = [];
merge_groups($groups, $ouput);
var_dump($ouput);
Tested in PHP 7.
Solution with simple loops. Foreach searches for a specific position and then increases the position. The number of positions can be more than 3. Positions like 123 123 23 are also possible.
$input = [
(object)[
"id" => 1,
"name" => "ASDAS",
"position" => 1,
],
(object)[
"id" => 2,
"name" => "ASDAS",
"position" => 1,
],
(object)[
"id" => 3,
"name" => "ASDAS",
"position" => 3,
],
(object)[
"id" => 4,
"name" => "ASDAS",
"position" => 2,
],
(object)[
"id" => 5,
"name" => "ASDAS",
"position" => 2,
],
(object)[
"id" => 6,
"name" => "ASDAS",
"position" => 3,
],
(object)[
"id" => 7,
"name" => "ASDAS",
"position" => 2,
],
(object)[
"id" => 8,
"name" => "ASDAS",
"position" => 1,
]
];
$minPos = min(array_column($input, "position"));
$arr = [];
$pos = $minPos;
while(true){
$found = false;
foreach($input as $key => $obj){
if($obj->position == $pos){
$arr[] = $obj;
unset($input[$key]);
++$pos;
$found = true;
}
}
if(empty($input)) break;
$minPos = min(array_column($input, "position"));
if(!$found AND $pos != $minPos){
$pos = $minPos;
}
}
var_dump($arr);
I currently have the below json response that the API is returning. I am able to return it using Laravel Eloquent. There are several users and each user has a several receipts. A receipt has types and status. I want to try to get the total sum amount for each receipt that is related to its type and status. I was able to return the below json response using
$this->user->with('receipts')->has('receipts')->get(['id', 'name']);
I have tried using multiple laravel collections methods https://laravel.com/docs/5.8/collections#available-methods But I am still unable to get the desired response.
[
{
"id": 1,
"name": "kent",
"receipts": [
{
"id": 1,
"user_id": 1,
"type_id": 1,
"status": 0,
"amount": 100
},
{
"id": 2,
"user_id": 1,
"type_id": 1,
"status": 0,
"amount": 100
},
{
"id": 3,
"user_id": 1,
"type_id": 2,
"status": 1,
"amount": 50
},
{
"id": 4,
"user_id": 1,
"type_id": 2,
"status": 0,
"amount": 30
},
{
"id": 5,
"user_id": 1,
"type_id": 2,
"status": 0,
"amount": 30
},
{
"id": 6,
"user_id": 1,
"type_id": 1,
"status": 0,
"amount": 20
},
{
"id": 7,
"user_id": 1,
"type_id": 1,
"status": 1,
"amount": 10
}
]
},
{
"id": 2,
"name": "allison",
"receipts": [
{
"id": 9,
"user_id": 2,
"type_id": 1,
"status": 0,
"amount": 20
}
]
}
]
I expect to get this:
[
{
"id": 1,
"name": "kent",
"receipts": [
{
"performance and deleted": 220,
"performance and not deleted": 10,
"project and deleted": 60,
"project and deleted": 50
}
]
},
{
"id": 2,
"name": "allison",
"receipts": [
{
"performance and deleted": 20,
"performance and not deleted": 0,
"project and deleted": 0,
"project and not deleted": 0
}
]
}
]
My main concern is to use laravel collection methods and easy to read code to get my expected result
In this way, I believe you get your expected result with nice readable code.
I'll assume that you have $users variable which contains a list of users in collection (And probably the receipts are already loaded).
// You need to name the keys as you desire. (I can't figure out the labels by the type_id and status numbers).
$statusPair = collect([
'performance and deleted' => [
'type_id' => 1,
'status' => 0,
],
'something' => [
'type_id' => 1,
'status' => 1,
],
'something 2' => [
'type_id' => 2,
'status' => 0,
],
'something 3' => [
'type_id' => 2,
'status' => 1,
],
]);
$data = $users->map(function ($user) use ($statusPair) {
$receipts = $user->receipts;
$sums = $statusPair->mapWithKeys(function ($pair, $statusLabel) use ($receipts) {
$filtered = $receipts;
foreach ($pair as $key => $value) {
$filtered = $filtered->where($key, $value);
}
$sum = $filtered->sum('amount');
return [
$statusLabel => $sum,
];
});
return [
'id' => $user->id,
'name' => $user->name,
'receipts' => $sums->toArray(),
];
});
i think this will help
$user->receipts->sum('amount');
I want my categories list be nice formatted while return to user. What I get from database is:
[
{
"id": 1,
"name": "pet",
"parent_id": null
},
{
"id": 2,
"name": "page",
"parent_id": null
},
{
"id": 3,
"name": "dog",
"parent_id": 1
},
{
"id": 4,
"name": "cat",
"parent_id": 1
},
{
"id": 5,
"name": "rodent",
"parent_id": 1
},...
I want it to keep tree structure, like:
{
"id": 1,
"name": "pet",
"parent_id": null,
"children": [
{
"id": 3,
"name": "dog",
"parent_id": 1
},
{
"id": 4,
"name": "cat",
"parent_id": 1
},...
etc.
Is there an easy way way to do it or I have to loop through the database results and create new organized array to return?
What is the best approach to do that? The problem is that the subcategories could also have subcategories. Or maybe i should just keep structure I get from the database and add children id's as an array (as I can refer to them anyway)?
I would be grateful for your help.
Thank you.
Solution:
function normalize_db_animals(){
$values[] = ["id" => 1, "name" => "pet", "parent_id" => null];
$values[] = ["id" => 2, "name" => "dog", "parent_id" => 1];
$values[] = ["id" => 3, "name" => "cat", "parent_id" => 1];
$values[] = ["id" => 4, "name" => "rodent", "parent_id" => 1];
$values[] = ["id" => 5, "name" => "wild", "parent_id" => null];
$values[] = ["id" => 6, "name" => "tiger", "parent_id" => 5];
$values[] = ["id" => 7, "name" => "rhino", "parent_id" => 5];
$normalize = function () use ($values) {
$tree = [];
$i = 0;
do {
$pet = $values[$i];
if ($pet['parent_id']) {
if (array_key_exists($pet['parent_id'], $tree)) {
$tree[$pet['parent_id']]['children'][] = $pet;
}
} else {
$tree[$pet['id']] = $pet;
}
$i++;
} while ($i < count($values));
return $tree;
};
$tree = $normalize();
echo json_encode($tree);
}
Result:
{"1":{"id":1,"name":"pet","parent_id":null,"children":[{"id":2,"name":"dog","parent_id":1},{"id":3,"name":"cat","parent_id":1},{"id":4,"name":"rodent","parent_id":1}]},"5":{"id":5,"name":"wild","parent_id":null,"children":[{"id":6,"name":"tiger","parent_id":5},{"id":7,"name":"rhino","parent_id":5}]}}
Try this one
$a = json_decode('[{
"id": 1,
"name": "pet",
"parent_id": null
},
{
"id": 2,
"name": "page",
"parent_id": null
},
{
"id": 3,
"name": "dog",
"parent_id": 1
},
{
"id": 4,
"name": "cat",
"parent_id": 1
},
{
"id": 5,
"name": "rodent",
"parent_id": 4
},
{
"id": 6,
"name": "rodent",
"parent_id": 2
}]');
$a = collect($a);
$filtered = $a;
foreach ($filtered as $key => $value) {
$children = $a->where('parent_id', $value->id);
if(!$children->isEmpty()){
$value->children = $children;
$filtered->forget(array_values(array_keys($children->toArray())));
}
}
dd($filtered);