Merge arrays in laravel including keys - php

I have 2 arrays and I want to merge them. (I can merge them) but I also need to include their unique keys in merged results and that part I cannot achieve.
sample
$prices = [
['112802' => "500000"],
['113041' => "1000000"],
];
$notes = [
['112802' => "note 2"],
['113041' => "note 1"],
];
$collection = collect($prices);
$zipped = $collection->zip($notes);
$zipped->toArray();
Unique keys are 112802 and 113041.
When I merge my array all I get is this:
[
[
"1000000",
"note 1"
],
[
"500000",
"note 2"
]
]
What I'm looking for is like this:
[
[
"id" => "112802",
"price" => "500000",
"note" => "note 2",
],
[
"id" => "113041",
"price" => "1000000",
"note" => "note 1",
]
}]
any suggestion?

This does what you want with the data you provide.
NOTE it will only work if your 2 arrays are the same size and the the keys are in the same order.
If this data comes from a database, it is likely it could have been produced in the format you actually wanted rather than having to fiddle with the data post fetch.
$prices = [
['112802' => "500000"],
['113041' => "1000000"],
];
$notes = [
['112802' => "note 2"],
['113041' => "note 1"],
];
$new = [];
foreach ($prices as $i=>$pr){
$k = key($pr);
$new[] = [ 'id' => $k,
'price' => $pr[$k],
'note' => $notes[$i][$k] ];
}
print_r($new);
RESULT
Array
(
[0] => Array (
[id] => 112802
[price] => 500000
[note] => note 2
)
[1] => Array (
[id] => 113041
[price] => 1000000
[note] => note 1
)
)

Here's another solution using some of Laravel's Collection methods.
It's not the most elegant, but it can be a starting point for you.
$prices = collect([
['112802' => "500000"],
['113041' => "1000000"],
])->mapWithKeys(function($item) {
// This assumes that the key will always be the ID and the first element is the price.
// Everythng else for each element will be ignored.
$id = array_keys($item)[0];
return [$id => ["id" => $id, "price" => reset($item)]];
});
$notes = collect([
['112802' => "note 2"],
['113041' => "note 1"],
])->mapWithKeys(function($item) {
$id = array_keys($item)[0];
return [$id => ["id" => $id, "note" => reset($item)]];
});
$result = $prices->zip($notes)->map(function ($item) {
// Feel free to call `toArray()` here if you don't want a Collection.
return collect($item)->mapWithKeys(function ($a) { return $a; });
});
Below is the $result (called using dd()).
Illuminate\Support\Collection {#1886 ▼
#items: array:2 [▼
0 => Illuminate\Support\Collection {#1888 ▼
#items: array:3 [▼
"id" => 112802
"price" => "500000"
"note" => "note 2"
]
}
1 => Illuminate\Support\Collection {#1889 ▼
#items: array:3 [▼
"id" => 113041
"price" => "1000000"
"note" => "note 1"
]
}
]
}
It's achieved by extracting the ID so that the zip can join there, but then we need a little hack with the map and mapWithKeys in the $result.
That's just because otherwise each element in $result will still have two separate arrays for $prices and $notes.

Related

Removing an element from a nested array in PHP

Am working on a Laravel application whereby I have an associative array that am to pass to an API endpoint, Before posting to the API, I want to delete the img key together with its value . I have tried to use unset function but it is not removing the img key
Array where I want to remove the image property
$a[] = [
0 => array:4 [
"name" => "Martoo nnn"
"relationship" => "Spouse"
"dob" => "2001-02-03"
"img" => "img.png"
]
1 => array:4 [
"name" => "sdsdsd sdsdsd"
"relationship" => "Child"
"dob" => "2019-04-04"
"img" => "img1.png"
]
2 => array:4 [
"name" => "sdsdsd sddds"
"relationship" => "Child"
"dob" => "2019-04-05"
"img" => "img2.png"
]
3 => array:4 [
"name" => "dssdsd dsdsd"
"relationship" => "Child"
"dob" => "2019-04-02"
"img" => "img3.png"
]
4 => array:4 [
"name" => "dssdsd dssdsd"
"relationship" => "Child"
"dob" => "2019-04-04"
"img" => "img4.png"
]
];
Unset method
$array = $a;
unset($array['img']);
//dd($a);
You can do something like this,
foreach ($array as $key => &$value) { // & defines changes will be made # value itself
unset($value['img']);
}
And Yes, I don't understand why you initialised $a as $a[]?
$newarray = array_filter($a, function($k) {
return $k != 'img';
}, ARRAY_FILTER_USE_KEY);
and pass this new array

Appending data in form request laravel inside array

I have a form request which I need to validate . If I dd the $request->all() it shows me the following result.
"adults_information" => array:1 [▼
0 => array:6 [▼
"first_name" => "Luke"
"last_name" => "Greer"
"dob_day" => "08"
"dob_month" => "01"
"dob_year" => 1935
"gender" => "M"
]]
"contact_name" => "Eula Dennis"
"mobile_number" => "7308001726"
What I want is to create extra field after dob_year such as dob which constist of calculation of dob_day,"dob_year","dob_month" . I want some line of code such that when I do dd($request->all()) . I want to get the output like this .
"adults_information" => array:1 [▼
0 => array:6 [▼
"first_name" => "Luke"
"last_name" => "Greer"
"dob_day" => "08"
"dob_month" => "01"
"dob_year" => 1935
"gender" => "M",
"dob"=>"1935-01-08"
]]
"contact_name" => "Eula Dennis"
"mobile_number" => "7308001726"
I tried $request->add() but it didn't work . Any help will be appriciated
The correct syntax is not $request->add but $request->request->add.
So:
$request->request->add([
'adults_information'=>$request->adults_information + ['dob' => '1935-01-08']
]);
$inputs = $request->all();
foreach($inputs['adults_information'] as $key => $info)
{
$dob = $info['dob_year'].'-'.
$info['dob_month'].'-'.
$info['dob_day'];
$inputs['adults_information'][$key]['dob'] = $dob;
}
$request->merge($inputs);
dd($request->all());
Hi u can use merge() with array_push to push a nested array.
$adults_information = $request->adults_information;
$insert = [
"first_name" => "Luke",
"last_name" => "Greer",
"dob_day" => "08",
"dob_month" => "01",
"dob_year" => 1935,
"gender" => "M",
"dob"=>"1935-01-08"
];
array_push($adults_information, $insert);
$request->merge('adults_information', $adults_information);
https://laravel.com/docs/5.6/requests
Hope this helps
You can use replace method for appending item to request object. For more details you can check Laravel API docs https://laravel.com/api/5.6/Illuminate/Http/Request.html#method_replace . For example.
$data = $request->all();
$data['appending_data_1'] = 'dummy value';
$data['appending_data_2'] = 'dummy value';
$request->replace($data);

Refactoring objects using Laravel Collections fails

What I try to do is that I need to return an array with key-value pairs from an array of objects.
From an api I get objects that looks something like this.
array:8 [▼
0 => TargetingSearch {#229 ▼
#data: array:6 [▼
"id" => "6005609368513"
"name" => "Software"
"audience_size" => 565991450
"path" => array:4 [▶]
"description" => ""
"topic" => "Technology"
]
#_type_checker: TypeChecker {#228 ▶}
}
The simple way to do it is to loop through the objects and push the values into an array.
$codes = [];
foreach($objects as $object) {
$codes[] = [
'id' => $object->id,
'name' => $object->name,
];
}
Which will return this that is exactly what I need.
['id' => 321, 'name' => "item1"],
['id' => 321, 'name' => "item1"],
['id' => 321, 'name' => "item1"],
I think that this is a little hard to manage and what I try to do is something a little more readable.
For example, by using the Laravel collection classes I could do something like this.
$codes = collect($objects)->pluck('id', 'name')->toArray();
The problem here is that this does not return the keys.
["item1" => "123"],
["item2" => "321"],
["item3" => "213"],
If I use
$codes = collect($objects)->only('id', 'name')->toArray();
It returns an empty array because the object itself is messing it all up.
anyone knows how to solve this?
You can use "map" method
collect($objects)->map(function ($item) {
return [
'id' => $item->id,
'name' => $item->name
];
});

How to union two collections without overriding any value

I am trying to get the union of two collections without overriding any value:
First Collection:
Collection {#246 ▼
#items: array [▼
0 => array [▼
"status" => "Invoice"
"letterPaymentAmount" => 4240.0
"BankAccountNo" => "SEK"
"Date" => "2017-07-15T16:32:22"
"DueDate" => "2017-07-28T00:00:00"
"ocr" => "3000000202"
"lastDatePayDay" => "28"
]]}
Second Collection
Collection {#246 ▼
#items: array [▼
0 => array [▼
"status": "Reminder",
"letterPaymentAmount": 4300,
"BankAccountNo": "SEK",
"Date": "2017-08-15T16:01:30",
"DueDate": "2017-08-30T00:00:00",
"ocr": "3000002406",
"lastDatePayDay": "30",
"lastDatePayMonth": "Aug",
"Country": "Singapore",
"Customer": "TickTack"
]]}
I want to acomplish this:
Collection {#246 ▼
#items: array [▼
0 => array [▼
"status" => "Invoice"
"letterPaymentAmount" => 4240.0
"BankAccountNo" => "SEK"
"Date" => "2017-07-15T16:32:22"
"DueDate" => "2017-07-28T00:00:00"
"ocr" => "3000000202"
"lastDatePayDay" => "28"],
1=> [
"status": "Reminder",
"letterPaymentAmount": 4300,
"BankAccountNo": "SEK",
"Date": "2017-08-15T16:01:30",
"DueDate": "2017-08-30T00:00:00",
"ocr": "3000002406",
"lastDatePayDay": "30",
"lastDatePayMonth": "Aug",
"Country": "Singapore",
"Customer": "TickTack" ]]}
I do not want to override any existing key or value just add them together.
I have tried union() but that overrides the existing keys and does not take keys that do not exist in first collection .
Any help would be much appreciated
Have you used concat()? An example is the following:
$col1 = collect([
['abc' => 1, 'dec' => 2],
['abc' => 1, 'dec' => 6]
]);
$col2 = collect([
['abc' => 3, 'dec' => 4, 'acd' => 2],
['abc' => 1, 'dec' => 8, 'acd' => 6],
]);
return $col1->concat($col2);
Note: if you use this on a collection without nested array then you might get different result from this one.
Use push to add new items to an existing collection without editing items.
$collection = collect([['a' => 'b']]);
$collection2 = collect([['c' => 'd']]);
$collection2->each(function ($e) use (&$collection) {
$collection->push($e);
});
Use merge()
$first = collect(['One','Two']);
$second = collect(['Two','Five']);
$merged = $first->merge($second);
// $merged->all();

Laravel collection how to remove a specific key from all items?

It sounded crazy simple to me at first but I can't find the solution!
Here is My collection :
Collection {#433
#items: array:432 [
0 => array:5 [
"word_id" => 12218
"name" => "ordered"
"rank" => 12217
"is_real" => 1
"id" => 1
]
1 => array:5 [
"word_id" => 12097
"name" => "one-dimensional"
"rank" => 12096
"is_real" => 1
"id" => 2
]
2 => array:5 [
"word_id" => 19679
"name" => "watery"
"rank" => 19678
"is_real" => 1
"id" => 3
]
.
.
.
But I want it to be like this :
Collection {#433
#items: array:432 [
0 => array:5 [
"name" => "ordered"
"id" => 1
]
1 => array:5 [
"name" => "one-dimensional"
"id" => 2
]
2 => array:5 [
"name" => "watery"
"id" => 3
]
.
.
.
How can it be done with laravel collection? Do I have to change my collection to array and do the manipulation myself? How?
Or you can also use
$collection = $collection ->map(function ($item) {
return collect($item)->forget(['work_id','rank','is_real']);
});
$collection = $collection->map(function ($item) {
return array_only($item, ['id', 'name']);
});
You can use the only() method.
The only method returns the items in the collection with the specified
keys
$collection = $collection->map(function ($item) {
return $item->only(['id', 'name'])
});
This way your collection still remains as collections;
Please note, only() method is only available for Laravel collections
not for an array
An alternative approach could be to use the Arr::only() helper to reduce the items:
$collection = $collection->map(static fn($item) => Arr::only($item, ['id', 'name']));

Categories