PHP Add null to array value if it doesn't exist - php

I'm generating data arrays and want to add 0/null to a specific month, where no data is present, but been struggling with it for few days.
I'm generating the final dataset array like this
foreach ($patients as $key => $item) {
$labels[] = $item['month'];
usort($labels, "compare_months");
$labels = array_unique($labels);
$chartData[ $item['brand_name'] ]['data'][] =
$item['patientsCount'];
$chartData[ $item['brand_name'] ]['brand_data'] = [
"name" => $item['brand_name'],
"color" => $item['color']
];
}
foreach ($chartData as $item) {
$pointRadius++;
$dataSet[] = [
'label' => $item['brand_data']['name'],
'data' => $item['data'],
'pointRadius' => $pointRadius,
'fill' => false,
'borderWidth' => 1,
'backgroundColor' => "#" . $item['brand_data']['color'],
'borderColor' => "#" . $item['brand_data']['color'],
];
}
$finalData[] = [
'labels' => $labels,
'datasets' => $dataSet
];
Which gives me this json response
[
{
"labels":[
"April",
"May",
"June",
"July"
],
"datasets":[
{
"label":"Medicine 1",
"data":[
1
],
"pointRadius":1,
"fill":false,
"borderWidth":1,
"backgroundColor":"#ea5f2d",
"borderColor":"#ea5f2d"
},
{
"label":"Medicine 2",
"data":[
1,
1,
1
],
"pointRadius":2,
"fill":false,
"borderWidth":1,
"backgroundColor":"#ffb400",
"borderColor":"#ffb400"
},
{
"label":"Medicine 3",
"data":[
1,
1,
2
],
"pointRadius":3,
"fill":false,
"borderWidth":1,
"backgroundColor":"#ff7777",
"borderColor":"#ff7777"
},
{
"label":"Medicine 4",
"data":[
1,
1,
2
],
"pointRadius":4,
"fill":false,
"borderWidth":1,
"backgroundColor":"#64a36f",
"borderColor":"#64a36f"
},
{
"label":"Medicine 5",
"data":[
2
],
"pointRadius":5,
"fill":false,
"borderWidth":1,
"backgroundColor":"#e7e6fc",
"borderColor":"#e7e6fc"
}
]
}
]
As you can see, for some items, the data object only contains 1 value which is wrong, because I need to add zeros to months, where there is no data.
Can this be done in MySQL or is it better to use PHP and how?
EDIT 1
Here is the array I am currently getting.
Array
(
[MEDICINE 1] => Array
(
[April] => 1
)
[MEDICINE 2] => Array
(
[April] => 1
[July] => 2
)
[MEDICINE 3] => Array
(
[April] => 1
[May] => 1
[July] => 2
)
[MEDICINE 4] => Array
(
[May] => 1
[July] => 3
)
[MEDICINE 5] => Array
(
[June] => 2
)
[MEDICINE 6] => Array
(
[July] => 1
)
)
As you can see some medicines have data for only one month and I want to add these months to the medicine array with 0 value, if there is no data.

Add this line after each foreach: if (count($item['data']) < 2) continue;. Because you need skip if length of data is smaller than 2.
foreach ($patients as $key => $item) {
if (count($item['data']) < 2) continue;
$labels[] = $item['month'];
usort($labels, "compare_months");
$labels = array_unique($labels);
$chartData[ $item['brand_name'] ]['data'][] =
$item['patientsCount'];
$chartData[ $item['brand_name'] ]['brand_data'] = [
"name" => $item['brand_name'],
"color" => $item['color']
];
}
foreach ($chartData as $item) {
$pointRadius++;
if (count($item['data']) < 2) continue;
$dataSet[] = [
'label' => $item['brand_data']['name'],
'data' => $item['data'],
'pointRadius' => $pointRadius,
'fill' => false,
'borderWidth' => 1,
'backgroundColor' => "#" . $item['brand_data']['color'],
'borderColor' => "#" . $item['brand_data']['color'],
];
}
$finalData[] = [
'labels' => $labels,
'datasets' => $dataSet
];

Related

Simplify & Optimize PHP Array

I am working on combining the array into a key with the count of repeated "option""code". My Request JSON is like this
[{
"productId": "DENSUS-MARK",
"options": [
{
"code": "HIGLIGT_OPTION_HANDLE"
},
{
"code": "HIGLIGT_OPTION_HANDLE1"
}
]
},
{
"productId": "DENSUS-MARK",
"options": [
{
"code": "HIGLIGT_OPTION_HANDLE"
}
]
},
{
"productId": "DENSUS-MARK-II",
"options": [
{
"code": "HIGLIGT_OPTION_HANDLE"
}
]
}]
After combing the "productID" and the count of ["options"]["code"] (For ProductId - DENSUS-MARK, the code "HIGLIGT_OPTION_HANDLE" count is 2. So I am getting a output like this.
{
"productId": "DENSUS-MARK",
"options": [
{
"code": "HIGLIGT_OPTION_HANDLE",
"count": 2
},
{
"code": "HIGLIGT_OPTION_HANDLE1",
"count": 1
}
]
},
{
"productId": "DENSUS-MARK-II",
"options": [
{
"code": "HIGLIGT_OPTION_HANDLE",
"count": 1
}
]
}
}
This is my current php code and I need to optimize & simply this below code
$datas = json_decode($arr,true);
$formattedData = [];
foreach ($datas as $f) {
foreach ($f['options'] as $option) {
$formattedData[$f['productID']]['productID'] = $f['productID'];
$formattedData[$f['productID']]['options']['code'][$option['code']][] = $option['code'];
}
}
foreach ($formattedData as &$data) {
$formattedOptions = [];
foreach ($data['options']['code'] as $key => $codes) {
$formattedOptions[] = [
'code' => $key,
'count' => count($codes)
];
}
$data = $formattedOptions;
}
print_r($formattedData);
Someone, could you please help me in this.
I don't know if this is the optimization you want. Meanwhile, less than two loops, I have not found. It's not quite the expected result, but you should be able to fix it if you need to.
With:
$input = array (
0 =>
array (
'productId' => 'DENSUS-MARK',
'options' =>
array (
0 =>
array (
'code' => 'HIGLIGT_OPTION_HANDLE',
),
1 =>
array (
'code' => 'HIGLIGT_OPTION_HANDLE1',
),
),
),
1 =>
array (
'productId' => 'DENSUS-MARK',
'options' =>
array (
0 =>
array (
'code' => 'HIGLIGT_OPTION_HANDLE',
),
),
),
2 =>
array (
'productId' => 'DENSUS-MARK-II',
'options' =>
array (
0 =>
array (
'code' => 'HIGLIGT_OPTION_HANDLE',
),
),
)
);
Then just:
$result = [];
foreach($input as $row) {
foreach($row['options'] as $value) {
$result[$row['productId']][$value['code']] ??=0;
$result[$row['productId']][$value['code']] += count($value);
}
}
var_export($result);
Results:
array (
'DENSUS-MARK' =>
array (
'HIGLIGT_OPTION_HANDLE' => 2,
'HIGLIGT_OPTION_HANDLE1' => 1,
),
'DENSUS-MARK-II' =>
array (
'HIGLIGT_OPTION_HANDLE' => 1,
),
)

Transpose subarray data from indexed to associative

I'm making an API for getting some data. My API gives object data like given, given object I wanted to format some data inside object:
{
"data": [
{
"productId": 55,
"productTitle": "Test product",
"variation": {
"Color": "Red",
"Size": "XS",
"din": "10190537",
"product_id": 55,
"name": [
"Color",
"Size"
],
"value": [
"Red",
"XS"
]
},
"din": "10190537",
"markets": [
{
"id": 11,
"name": "paytmmall",
"displayName": "PayTm Mall",
"identifierName": "Product_Id"
}
]
}
]
}
In this object I want data like given
{
"data": [
{
"productId": 55,
"productTitle": "this is test from hariom",
"variation": {
"Color": "Red",
"Size": "XS",
"din": "10190537",
"product_id": 55,
"variationTypes": [
{
"name": "Color",
"value": "Red"
},
{
"name": "Size",
"value": "XS"
}
],
},
"din": "10190537",
"markets": [
{
"id": 11,
"name": "paytmmall",
"displayName": "PayTm Mall",
"identifierName": "Product_Id"
}
]
}
]
}
Here Is my Controller Name
public function MarketMapping(Request $request)
{
$sellerId = Auth::guard('seller-api')->user();
$page = $request->has('pageNumber') ? $request->get('pageNumber') : 1;
$limit = $request->has('perPage') ? $request->get('perPage') : 10;
$variationFromInvTbl = ProductInventory::select('Color', 'Size', 'din', 'product_id')->where('seller_id', $sellerId->id)->where('status', 'active')->limit($limit)->offset(($page - 1) * $limit)->get();
$dataArray = array();
foreach($variationFromInvTbl as $key => $varitionValue)
{
$prodtsFromLivetbl = ProductsLive::select('productTitle', 'product_id')->where('product_id', $varitionValue->product_id)->get();
foreach ($prodtsFromLivetbl as $key => $value)
{
$marketChannelData = DB::table('market_channels')
->join('sellers_market_channels', 'market_channels.name', '=', 'sellers_market_channels.key')
//->join('market_product_mappings', 'market_channels.id', '=', 'market_product_mappings.market_id')
->select('market_channels.id','market_channels.name', 'market_channels.displayName','market_channels.identifierName') //'market_product_mappings.identifierValue'
->where('sellers_market_channels.seller_id', $sellerId->id)
->where('sellers_market_channels.value', 1)
->get();
$maketProductMap = MarketProductMapping::where('seller_id', $sellerId->id)->where('product_id', $varitionValue->product_id)->where('din', $varitionValue->din)->pluck('identifierValue');
if (count($maketProductMap))
{
$marketChannelData[$key]->value = $maketProductMap[0];
}
$varitionValue['name']= array_keys($varitionValue->only(['Color', 'Size']));
$varitionValue['value'] = array_values($varitionValue->only(['Color', 'Size']));
$dataObject = ((object)[
"productId" => $value->product_id,
"productTitle" => $value->productTitle,
"variation" => $varitionValue,
"din" => $varitionValue['din'],
"markets" => $marketChannelData
]);
array_push($dataArray,$dataObject);
}
}
if($variationFromInvTbl)
{
$response['success'] = true;
$response["page"] = $page;
$response["itemPerPage"] = $limit;
$response["totalRecords"] = $this->CountMarketMapping($page, $limit, $sellerId->id);
$response['data'] = $dataArray;
return response()->json($response, 200);
}else{
$response['success'] = false;
$response['data'] = $prodtsFromLivetbl;
return response()->json($response, 409);
}
}
You are using laravel's only() method which returns an associative array.
You wish to convert each key-value pair into a subarray containing two associative elements -- the original key will be the value of the name element
and the original value will be the value of the value element.
By passing the original array keys and array values into array_map(), you can iterate them both synchronously.
compact() is a perfect native function to create the desired associative subarrays from the iterated parameters.
Code: (Demo)
$variations = $varitionValue->only(['Color', 'Size']);
$dataObject = (object)[
// ... your other data
'variations' => array_map(
function($name, $value) {
return compact(['name', 'value']);
},
array_keys($variations),
$variations
),
// ...your other data
];
var_export($dataObject);
Output:
(object) array(
'variations' =>
array (
0 =>
array (
'name' => 'Color',
'value' => 'Red',
),
1 =>
array (
'name' => 'Size',
'value' => 'XS',
),
),
)
This script will help you
<?php
$data = [
"variation" => [
[
"Color" => "Red",
"Size" => "XS",
"din" => "10190537",
"product_id" => 55,
"name" => [
"0" => "Color",
"1" => "Size"
],
"value" => [
"0" => "Red",
"1" => "XS"
]
]
]
];
for ($i=0; $i < count($data["variation"]); $i++) {
$data["variation"][$i]["data"]["name"] = $data["variation"][$i]["name"];
$data["variation"][$i]["data"]["value"] = $data["variation"][$i]["value"];
unset($data["variation"][$i]["name"]);
unset($data["variation"][$i]["value"]);
}
print_r($data);
output
Array
(
[variation] => Array
(
[0] => Array
(
[Color] => Red
[Size] => XS
[din] => 10190537
[product_id] => 55
[data] => Array
(
[name] => Array
(
[0] => Color
[1] => Size
)
[value] => Array
(
[0] => Red
[1] => XS
)
)
)
)
)

How do I move an array element with a known key weight of an array in PHP?

Having a brain freeze over a fairly trivial problem. If I start with an array like this:
$my_array = array(
1 => [
"id" => 1,
"weight" => 0
],
2 => [
"id" => 2,
"weight" => -1
],
3 => [
"id" => 3,
"weight" => 0
],
4 => [
"id" => 4,
"weight" => -1
],
);
and i will do a function that move the keys of the array to key + 'weight'. So the result gona be like this:
$my_array = array(
1 => [
"id" => 2,
"weight" => -1
],
2 => [
"id" => 1,
"weight" => 0
],
3 => [
"id" => 4,
"weight" => -1
],
4 => [
"id" => 3,
"weight" => 0
],
);
What is the most efficient way to do this?
Here is the function if it can help some people
function reorder_array(&$my_array) {
foreach ($my_array as $key => $object) {
$move = $object['weight'];
$arr = $my_array;
if ($move == 0 || !isset($arr[$key])) {
continue;
}
$i = 0;
foreach($arr as &$val){
$val = array('sort' => (++$i * 10), 'val' => $val);
}
$arr[$key]['sort'] = $arr[$key]['sort'] + ($move * 10 + ($key == $key ? ($move < 0 ? -5 : 5) : 0));
uasort($arr, function($a, $b) {
return $a['sort'] > $b['sort'];
});
foreach($arr as &$val) {
$val = $val['val'];
}
$my_array = $arr;
}
}
Source of my solution

Group an array based on common value

I have an array with common product code & product name.
For each product_code can have two types of cha_sty_id i.e push or pull.
This is an array structure I have.
$array = [
0 => [
"product_code" => "67021687",
"product_name" => "Spaces",
"cha_sty_id" => "PUSH",
"chs_name" => "WF"
],
1 => [
"product_code" => "67021687",
"product_name" => "Spaces",
"cha_sty_id" => "PUSH",
"chs_name" => "WFR"
],
2 => [
"product_code" => "67021687",
"product_name" => "Spaces",
"cha_sty_id" => "PUSH",
"chs_name" => "STK Food"
],
3 => [
"product_code" => "67021687",
"product_name" => "Spaces",
"cha_sty_id" => "PULL",
"chs_name" => "4 Stars"
],
4 => [
"product_code" => "67021687",
"product_name" => "Spaces",
"cha_sty_id" => "PULL",
"chs_name" => "5 Stars"
],
5 => [
"product_code" => "67021687",
"product_name" => "Spaces",
"cha_sty_id" => "PULL",
"chs_name" => "Modern Thai"
],
6 => [
"product_code" => "67021687",
"product_name" => "Spaces",
"cha_sty_id" => "PULL",
"chs_name" => "BBQ Buffet"
],
7 => [
"product_code" => "67021687",
"product_name" => "Spaces",
"cha_sty_id" => "PULL",
"chs_name" => "Chinese"
]
];
Now I want result something like:
0 => [
'product_code' => 67021687,
'product_name' => 'Spaces.
'push => array(....ALL chs_name for push),
'pull' => array with chs_name for pull
]
I have tried some code
$list = array();
foreach ($records as $data) {
$list[$data['product_code']][] = $data;
if($data['cha_sty_id'] == 'PUSH') {
$list[$data['product_code']]['push'] = $data['chs_name'];
} else {
$list[$data['product_code']]['pull'] = $data['chs_name'];
}
}
But I could not solve it.
Can anybody pls help me.
Thank You.
How about this modify your foreach loop to this:
$list = array();
foreach ($records as $data) {
$code = $data['product_code']; // as key
if (!isset($list[$code])) { // set new array if not exist
$list[$code] = array("product_code" => $code, "product_name" => $data['product_name'], "push" => [], "pull" => []);
}
$subKey = strtolower($data['cha_sty_id']); // get push / pull as new subkey
$list[$code][$subKey][] = $data['chs_name']; // append to the array
}
You can use array_values to remove the code keys from $list after the loop if not needed
You can use array_walk,array_push
$res = [];
array_walk($array, function($v, $k) use (&$res){
if(in_array($v['product_code'], array_column($res, 'product_code'))){
array_push($res[$v['product_code']]["push"], $v['chs_name']);
array_push($res[$v['product_code']]["pull"], $v['chs_name']);
}else{
$res[$v['product_code']] = [
"product_code" => $v['product_code'],
"product_name" => $v['product_name'],
"push" => [$v['chs_name']],
"pull" => [$v['chs_name']]
];
}
});
echo '<pre>';
print_r(array_values($res));
DEMO HERE
There is no need for any conditional expressions while partially pivoting your data into groups. Use the product_code values as temporary first level keys and use the cha_sty_id values as dynamic second level keys. Re-index the result array after the loop finishes with array_values().
One approach uses a body-less foreach as explained here.
Code: (Demo)
$result = [];
foreach (
$array
as
[
'product_code' => $productCode,
'cha_sty_id' => $id,
'product_code' => $result[$code]['product_code'],
'product_name' => $result[$code]['product_name'],
'chs_name' => $result[$code][strtolower($id)][]
]
);
var_export(array_values($result));
A more traditional style is to group and pivot inside the body of the loop.
Code: (Demo)
$result = [];
foreach ($array as $row) {
$result[$row['product_code']]['product_code'] = $row['product_code'];
$result[$row['product_code']]['product_name'] = $row['product_name'];
$result[$row['product_code']][strtolower($row['cha_sty_id'])][] = $row['chs_name'];
}
var_export(array_values($result));
Due to the fact that the group logic is possibly going to return an array size that differs from the input array, array_reduce() is the most appropriate functional iterator for this task.
Code: (Demo)
var_export(
array_values(
array_reduce(
$array,
function($result, $row) {
$result[$row['product_code']]['product_code'] = $row['product_code'];
$result[$row['product_code']]['product_name'] = $row['product_name'];
$result[$row['product_code']][strtolower($row['cha_sty_id'])][] = $row['chs_name'];
return $result;
},
[]
)
)
);
All techniques above produce the exact same result.

How to add array if key value is same

Hi i having difficulty to trace an multi dimensional array.
[
0 => array:7 [
"date" => "2016-01-19"
"placement_id" => 1
"requests" => 18
"revenue" => 1
],
1 => array:7 [
"date" => "2016-01-19"
"placement_id" => 1
"requests" => 2
"revenue" => 0.2
]
];
if placement_id are same i want resulted array:
1 => array:7 [
"date" => "2016-01-19"
"placement_id" => 1
"requests" => 20
"revenue" => 1.2
]
The requirement is to produce an output array that has:
Items with the same 'placement_id' having the 'requests' and revenue summed.
The key of the entry in the output array will be be the 'placement_id'.
That means that the output array will be smaller that the input array.
I decided to use the array_reduce function. There is no special reason, foreach loops work fine. It isn't any more efficient. It is just different.
The important point about array_reduce is that the $carry (accumulator) can be an array...
Working example at Eval.in
The code:
$outArray = array();
$outArray = array_reduce($src,
function($carry, $item) { // accumulate values if possible
$carryKey = $item['placement_id']; // array key
if (isset($carry[$carryKey])) { // accumulate values
$carry[$carryKey]['requests'] += $item['requests'];
$carry[$carryKey]['revenue'] += $item['revenue'];
} else { // is new - add to the output...
$carry[$carryKey] = $item;
}
return $carry;
},
array() /* accumulator ($carry) is an internal variable */);
Output Array:
array (2) [
'1' => array (4) [
'date' => string (10) "2016-01-19"
'placement_id' => integer 1
'requests' => integer 20
'revenue' => float 1.2
]
'666' => array (4) [
'date' => string (10) "2016-04-01"
'placement_id' => integer 666
'requests' => integer 266
'revenue' => float 666.20000000000005
]
]
Test Data:
$src = array(
0 => array(
"date" => "2016-01-19",
"placement_id" => 1,
"requests" => 18,
"revenue" => 1,
),
1 => array(
"date" => "2016-04-01",
"placement_id" => 666,
"requests" => 266,
"revenue" => 666.2,
),
2 => array(
"date" => "2016-01-19",
"placement_id" => 1,
"requests" => 2,
"revenue" => 0.2,
),
);
Taking that $arr parameter is the array that you show, we could create a function like this to look for duplicates ids and aggregate them. The $output array will return the results.
public function checkArray($arr) {
$output = array();
$deleted = array();
foreach($arr as $key => $value){
if (!in_array($key, $deleted)) {
$entry = array();
$entry['date'] = $value['date'];
$entry['placement_id'] = $value['placement_id'];
$entry['requests'] = $value['requests'];
$entry['revenue'] = $value['revenue'];
foreach($arr as $key2 => $value2){
if($key != $key2 && $value['placement_id'] == $value2['placement_id']){
$entry['requests'] += $value2['requests'];
$entry['revenue'] += $value2['revenue'];
$deleted[] = $key2;
}
}
$output[] = $entry;
}
}
return $output;
}

Categories