This question already has answers here:
Merge two arrays into one associative array
(2 answers)
Closed 7 months ago.
I want to change the following php array
"extra_charge_item" => [
0 => "Massage",
1 => "Pool table",
2 => "Laundry"
],
"extra_charge_description" => [
0 => "Paid",
1 => "Paid",
2 => "We wash everything"
],
"extra_charge_price" => [
0 => "200",
1 => "100",
2 => "1000"
],
I haven't been able to solve for a whole 2hrs
This is the expected output
"new_data" => [
0 => [
"Maasage", "Paid", "200"
],
1 => [
"Pool table", "Paid", "100"
],
2 => [
"Laundry", "we wash everything", "1000"
]
]
Rather than doing all the work for you, here's some pointers on one way to approach this:
If you are happy to assume that all three sub-arrays have the same number of items, you can use array_keys to get those keys from whichever you want.
Once you have those keys, you can use a foreach loop to look at each in turn.
For each key, use square bracket syntax to pluck the three items you need.
Use [$foo, $bar, $baz] or array($foo, $bar, $baz) to create a new array.
Assign that array to your final output array, using the key from your foreach loop.
Just use foreach with key => value
$data = [
"extra_charge_item" => [
0 => "Massage",
1 => "Pool table",
2 => "Laundry"
],
"extra_charge_description" => [
0 => "Paid",
1 => "Paid",
2 => "We wash everything"
],
"extra_charge_price" => [
0 => "200",
1 => "100",
2 => "1000"
],
];
$newData = [];
foreach ($data as $value) {
foreach ($value as $k => $v) {
$newData[$k][] = $v;
}
}
var_dump($newData);
I found an answer. Seems someone else had the same problem
Merge two arrays into one associative array
Here's the solution for my case;
//These are arrays passed from front end in the name attribute e.g extra_charge_item[] e.t.c
$extra_charge_item_array = $request->input('extra_charge_item');
$extra_charge_description_array = $request->input('extra_charge_description');
$extra_charge_price_array = $request->input('extra_charge_price');
$new_extra_charges_data = array_map(
function ($item, $description, $price) {
return [
'item' => $item,
'description' => $description,
'price'=> $price
];
}, $extra_charge_item_array, $extra_charge_description_array, $extra_charge_price_array);
//save the data
foreach ($new_extra_charges_data as $extra_charge) {
Charge::create([
'item' => $extra_charge['item'],
'description' => $extra_charge['description'],
'price' => $extra_charge['price']
]);
}
Related
I've got a 4-level nested array, each level represent a hiereachy in an organization. Each level's key is the hierarchy value, and inside it there is the id of it in the array. The last level is only the value-id pair:
$data = [
"top_level_data1" => [
'top_level_id' => 0,
'sub_level_1' => [
'sub_level_1_id' => 0,
'sub_level_2_data1' => [
'sub_level_2_id' => 0,
'sub_level_2_data' => [
0 => "some_val"
1 => "some_other_val"
]
]
]
],
"top_level_data2" => [
'level_1_id' => 1,
'sub_level_1_other' => [
'sub_level_1_id' => 1,
'sub_level_2_data2' => [
'sub_level_2_id' => 1,
'sub_level_3_data1' => [
2 => "another_val"
3 => "bar"
4 => "foo"
]
],
'sub_level_2_data3' => [
'sub_level_2_id' => 2,
'sub_level_3_data2' => [
5 => "foobar"
6 => "hello"
7 => "goodbye"
]
]
]
]
];
I want to extract it to separate arrays that would contain the hierarchy value-id pairs.
Expected output from the above example (without the ids of the above level):
$top_level = [
0 => "top_level_data1",
1 => "top_level_data2"
]
$sub_level_1 = [
0 => "sub_level_1",
1 => "sub_level_1_other"
]
$sub_level_2 = [
0 => "sub_level_2_data1",
1 => "sub_level_2_data2",
2 => "sub_level_2_data3"
]
$sub_level_3 = [
0 => "some_val"
1 => "some_other_val"
2 => "another_val"
3 => "bar"
4 => "foo"
5 => "foobar"
6 => "hello"
7 => "goodbye"
]
I've tried using the RecursiveIterator but that does not work (At first I wanted to use it just to check if it iterates correctly, even before assignting the key-values as I wanted, but it just doesn't do it as I wanted):
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($data));
foreach($it as $key => $val) {
$level[$it->getDepth()][] = $val;
}
This can do it:
$result = [];
$recursive = null;
$recursive = function($args,$level=0) use (&$recursive,&$result){
foreach($args as $k=>$v){
if(is_array($v)){
$result[$level][]=$k;
$recursive($v,$level+1);
} else if(is_string($v)){
$result[$level][]=$v;
}
}
};
$recursive($data);
var_export($result);
But your expected output isn't ok. Because i think sub_level_2_data must be sub_level_3_data (in the $data array above). And the hole sub_level_3*level is missing in your expected output.
With this code you get an result array instead of separate filled variables.
Will not explain it in detail, but try to understand whats happening here and you can learn some new php stuff.
I have an array with a structure like:
$arr = [
'data1' => [ /* some data */],
'data2' => [
'sub-data1' => [
[
'id' => 1
'status' => 'active'
],
[
'id' => 2
'status' => 'not-active'
]
],
'sub-data2' => [
[
'id' => 3
'status' => 'active'
],
[
'id' => 4
'status' => 'active'
]
]
]
]
Is there a simple way in which I can count how many sub-dataxxx have any item with a status is active?
I have managed to do this with nested foreach loops, but I'm wondering if there is a more simple method?
The above example should show the number of active entries as 2, as there are 2 sub-data elements with active statuses. This ignores any non-active statuses.
Edit: To clarify my expected result
I am not wanting to count the number of status = active occurrences. I'm wanting to count the number of sub-dataxxx elements that contain an element with status = active.
So in this instance, both of sub-data1 and sub-data2 contain sub-elements that contain status = active, therefore my count should be 2.
you can do it quite easily with a function like this
function countActiveSubData(array $data): int
{
return array_reduce($data, function ($res, $sub) {
foreach ($sub as $d) {
if ('active' === $d['status']) {
return $res + 1;
}
}
return $res;
}, 0);
}
you can call it on a single data or if you want to get the result for entire $arr you can call it like this
$result = array_map('countActiveSubData', $arr);
// the result will be [
'data1' => 0,
'data2'=> 2
....
]
So I found an answer which is supposed to work, however it doesn't appear too...
Already accepted answer with the same issue.
I have got the following array called $banners:
[
0 => [
"bannerCustomTemplate" => 0,
"bannerId" => 1,
"bannerType" => 1,
"bannerTitle" => "Merry",
"bannerStrapline" => "Christmas",
"bannerPeriod" => "2018-12-01 to 2018-12-10",
"bannerText" => "Christmas opening hours"
],
1 => [
"bannerCustomTemplate" => 0,
"bannerId" => 7,
"bannerType" => 2,
"bannerTitle" => "Easter",
"bannerStrapline" => "Test",
"bannerPeriod" => "2018-12-04 to 2018-12-12",
"bannerText" => "dsadasdaas"
]
]
The answers I have read suggest $all_banners = call_user_func_array('array_merge', $banners);.
However this is giving me:
[
"bannerCustomTemplate" => 0,
"bannerId" => 7,
"bannerType" => 2,
"bannerTitle" => "Easter",
"bannerStrapline" => "Test",
"bannerPeriod" => "2018-12-04 to 2018-12-12",
"bannerText" => "dsadasdaas"
]
Seems like it's just replacing rather than merging. Anyone got any ideas?
Edit
Just read the following comment
Little note here. The updated variant with unpacking array doesn't work with string keys. But the first one works perfect. Just keep in mind this. – Alliswell
So I have now updated my code with another solutions, with the same results.
Edit 2
Well, merging is merging not replacing. So what I expect is:
[
"bannerCustomTemplate" => [ 0, 0 ],
"bannerId" => [ 1, 7 ],
"bannerType" => [ 1, 2 ],
"bannerTitle" => [ "Merry", "Easter" ]
"bannerStrapline" => [ "Christmas", "Test" ]
"bannerPeriod" => [ "2018-12-01 to 2018-12-10", "2018-12-04 to 2018-12-12" ]
"bannerText" => ["Christmas opening hours", "dsadasdaas" ]
]
If all your arrays are known to contain the same keys in the same order, this is probably easiest:
$data = [
['foo' => 'bar', 'baz' => 42],
['foo' => 'baz', 'baz' => 69]
];
$result = array_combine(array_keys($data[0]), array_map(null, ...$data));
This uses the useful behaviour of array_map with null as the callback to take one element from each input array and return a new combined array.
I have an array based MySql database.
This is the array.
[
0 => [
'id' => '1997'
'lokasi_terakhir' => 'YA4121'
]
1 => [
'id' => '1998'
'lokasi_terakhir' => 'PL2115'
]
2 => [
'id' => '1999'
'lokasi_terakhir' => 'PL4111'
]
]
How can I get the element lokasi_terakhir that grouped by the first character ? What the best way ?
This is the goal :
[
"Y" => 1,
"P" => 2
]
Please advise
Here are two refined methods. Which one you choose will come down to your personal preference (you won't find better methods).
In the first, I am iterating the array, declaring the first character of the lokasi_terakhir value as the key in the $result declaration. If the key doesn't yet exist in the output array then it must be declared / set to 1. After it has been instantiated, it can then be incremented -- I am using "pre-incrementation".
The second method first maps a new array using the first character of the lokasi_terakhir value from each subarray, then counts each occurrence of each letter.
(Demonstrations Link)
Method #1: (foreach)
foreach($array as $item){
if(!isset($result[$item['lokasi_terakhir'][0]])){
$result[$item['lokasi_terakhir'][0]]=1; // instantiate
}else{
++$result[$item['lokasi_terakhir'][0]]; // increment
}
}
var_export($result);
Method #2: (functional)
var_export(array_count_values(array_map(function($a){return $a['lokasi_terakhir'][0];},$array)));
// generate array of single-character elements, then count occurrences
Output: (from either)
array (
'Y' => 1,
'P' => 2,
)
You can group those items like this:
$array = [
0 => [
'id' => '1997',
'lokasi_terakhir' => 'YA4121'
],
1 => [
'id' => '1998',
'lokasi_terakhir' => 'PL2115'
],
2 => [
'id' => '1999',
'lokasi_terakhir' => 'PL4111'
]
];
$result = array();
foreach($array as $item) {
$char = substr($item['lokasi_terakhir'], 0, 1);
if(!isset($result[$char])) {
$result[$char] = array();
}
$result[$char][] = $item;
}
<?php
$array=[
0 => [
'id' => '1997',
'lokasi_terakhir' => 'YA4121'
],
1 => [
'id' => '1998',
'lokasi_terakhir' => 'PL2115'
],
2 => [
'id' => '1999',
'lokasi_terakhir' => 'PL4111'
]
];
foreach($array as $row){
$newArray[]=$row['lokasi_terakhir'][0];
}
print_r(array_flip(array_unique($newArray)));
this code gets the first letter of the fields lokasi_terakhir , get the unique values to avoid duplicates and just flips the array to get the outcome you want.
The output is this :
Array ( [Y] => 0 [P] => 1 )
I have below array, I need to append a new array inside $newData['_embedded']['settings']['web/vacation/filters']['data'], How can I access and append inside it ?
$newData = [
"id" => "47964173",
"email" => "abced#gmail.com",
"firstName" => "Muhammad",
"lastName" => "Taqi",
"type" => "employee",
"_embedded" => [
"settings" => [
[
"alias" => "web/essentials",
"data" => [],
"dateUpdated" => "2017-08-16T08:54:11Z"
],
[
"alias" => "web/personalization",
"data" => [],
"dateUpdated" => "2016-07-14T10:31:46Z"
],
[
"alias" => "wizard/login",
"data" => [],
"dateUpdated" => "2016-09-26T07:56:43Z"
],
[
"alias" => "web/vacation/filters",
"data" => [
"test" => [
"type" => "teams",
"value" => [
0 => "09b285ec-7687-fc95-2630-82d321764ea7",
1 => "0bf117b4-668b-a9da-72d4-66407be64a56",
2 => "16f30bfb-060b-360f-168e-1ddff04ef5cd"
],
],
"multiple teams" => [
"type" => "teams",
"value" => [
0 => "359c0f53-c9c3-3f88-87e3-aa9ec2748313"
]
]
],
"dateUpdated" => "2017-07-03T09:10:36Z"
],
[
"alias" => "web/vacation/state",
"data" => [],
"dateUpdated" => "2016-12-08T06:58:57Z"
]
]
]
];
$newData['_embedded']['settings']['web/vacation/filters']['data'] = $newArray;
Any Hint to quickly append it, I don't want to loop-in and check for keys inside loops.
The settings subarray is "indexed". You first need to search the alias column of the subarray for web/vacation/filters to find the correct index. Using a foreach loop without a break will mean your code will continue to iterate even after the index is found (bad coding practice).
There is a cleaner way that avoids a loop & condition & break, use array_search(array_column()). It will seek your associative element, return the index, and immediately stop seeking.
You can use the + operator to add the new data to the subarray. This avoids calling a function like array_merge().
Code: (Demo)
if(($index=array_search('web/vacation/filters',array_column($newData['_embedded']['settings'],'alias')))!==false){
$newData['_embedded']['settings'][$index]['data']+=$newArray;
}
var_export($newData);
Perhaps a more considered process would be to force the insert of the new data when the search returns no match, rather than just flagging the process as unsuccessful. You may have to tweak the date generation for your specific timezone or whatever... (Demo Link)
$newArray=["test2"=>[
"type" =>"teams2",
"value" => [
0 => "09b285ec-7687-fc95-2630-82d321764ea7",
1 => "0bf117b4-668b-a9da-72d4-66407be64a56",
2 => "16f30bfb-060b-360f-168e-1ddff04ef5cd"
],
]
];
if(($index=array_search('web/vacation/filters',array_column($newData['_embedded']['settings'],'alias')))!==false){
//echo $index;
$newData['_embedded']['settings'][$index]['data']+=$newArray;
}else{
//echo "couldn't find index, inserting new subarray";
$dt = new DateTime();
$dt->setTimeZone(new DateTimeZone('UTC')); // or whatever you are using
$stamp=$dt->format('Y-m-d\TH-i-s\Z');
$newData['_embedded']['settings'][]=[
"alias" => "web/vacation/filters",
"data" => $newArray,
"dateUpdated" => $stamp
];
}
You need to find the key that corresponds to web/vacation/filters. For Example you could use this.
foreach ($newData['_embedded']['settings'] as $key => $value) {
if ($value["alias"]==='web/vacation/filters') {
$indexOfWVF = $key;
}
}
$newData['_embedded']['settings'][$indexOfWVF]['data'][] = $newArray;
From the comments. Then you want to merge the arrays. Not append them.
$newData['_embedded']['settings'][$indexOfWVF]['data'] = array_merge($newData['_embedded']['settings'][$indexOfWVF]['data'],$newArray);
Or (if it's always Filter1):
$newData['_embedded']['settings'][$indexOfWVF]['data']['Filter1'] = $newArray['Filter1'];