I have a problem approaching an issue i have, i need to group arrays by key value
I have 3 foreach functions
foreach ($report_phonecall as $key=>$value) {
$phonecalls[$value['datum']] = $value['broj'];
};
foreach ($report_meeting as $key=>$value) {
$meetings[$value['datum']] = $value['broj'];
}
foreach ($report_notes as $key=>$value) {
$notes[$value['datum']] = $value['broj'];
}
That give me array
$phonecall = Array ( [2016-07-13] => 2 [2016-07-14] => 1 [2016-07-19] =>1 )
$meetings = Array ( [2016-07-13] => 1 [2016-07-14] => 1 )
$notes = Array ( [2016-07-19] => 1 )
I need to merge them into 1 array foreach date like this
Array(2016-07-13 => array([phonecalls]=>2, [meetings]=>1, [notes]=>0)) 2016-07-14 => array([phonecalls]=>1, [meetings]=> 1, [notes]=>0).... etc
I want to group/sort them by key value.
Going by
$group_reports[$value[key]] = $value['broj'][$phonecalls][$meetings][$notes]
Im not sure how to define it
How about like this?
$phonecall = ['2016-07-13' => 2, '2016-07-14' => 1, '2016-07-19' => 1];
$meetings = ['2016-07-13' => 1, '2016-07-14' => 1];
$notes = ['2016-07-19' => 1];
// Get *all* possible dates
$keys = array_unique(array_keys($phonecall+$meetings+$notes));
foreach($keys as $key) {
$final[$key] = [
'phonecalls' => isset($phonecall[$key]) ? $phonecall[$key] : 0,
'meetings' => isset($meetings[$key]) ? $meetings[$key] : 0,
'notes' => isset($notes[$key]) ? $notes[$key] : 0
];
}
Please use below code for merge array
$finalArr = array();
foreach($phonecall as $key=>$val){
$finalArr[$key]['phonecalls'] = $val;
$finalArr[$key]['meetings'] = 0;
$finalArr[$key]['notes'] = 0;
}
foreach($meetings as $key=>$val){
if(array_key_exists($key, $finalArr)){
$finalArr[$key]['meetings'] = $val;
} else {
$finalArr[$key]['phonecalls'] = 0;
$finalArr[$key]['meetings'] = $val;
$finalArr[$key]['notes'] = 0;
}
}
foreach($notes as $key=>$val){
if(array_key_exists($key, $finalArr)){
$finalArr[$key]['notes'] = $val;
} else {
$finalArr[$key]['phonecalls'] = 0;
$finalArr[$key]['meetings'] = 0;
$finalArr[$key]['notes'] = $val;
}
}
Related
I am looking to store sum of all keys inside an array here is my example code
<?php
// Sample data
$category = (object) ['category_name' => '32459*1500*lab*1,32460*400*lab*1,32461*600*lab*1'];
// process
$category_sale_data = explode(',', $category->category_name);
foreach ($category_sale_data as $key => $value) {
list($sale_key, $sale_value) = explode('*', $value);
$category->sale_data[$sale_key][] = $sale_value;
//$category->sale_data_sum[$sale_key][] += $sale_value;
}
// display
print_r($category);
getting this output working example -> https://3v4l.org/NAKfb#v7.0.0
Here is expected to get //$category->sale_data_sum[$sale_key][] +=
$sale_value;
I am expected output like this
stdClass Object
(
[category_name] => 32459*1500*lab*1,32460*400*lab*1,32461*600*lab*1
[sale_data] => Array
(
[32459] => Array
(
[0] => 1500
)
[32460] => Array
(
[0] => 400
)
[32461] => Array
(
[0] => 600
)
)
[sale_data_sum] => 2500
)
Simply do this:
$category->sale_data_sum = 0; // initiate key
foreach ($category_sale_data as $key => $value) {
list($sale_key, $sale_value) = explode('*', $value);
$category->sale_data[$sale_key][] = $sale_value;
$category->sale_data_sum += $sale_value; // add each sale value
}
$category = [ 'category_name' => '32459*1500*lab*1,32460*400*lab*1,32461*600*lab*1' ];
// category_name
$result['category_name'] = $category['category_name'];
// sale_data
$splitted = preg_split('/[*,]/', $category['category_name']);
for($i = 0; $i < count($splitted); $i += 4) {
$result['sale_data'][$splitted[$i]] = $splitted[$i + 1];
}
// sale_data_sum
$result['sale_data_sum'] = array_sum($result['sale_data']);
print_r($result);
Try this
<?php
// Sample data
$category = (object) ['category_name' => '32459*1500*lab*1,32460*400*lab*1,32461*600*lab*1'];
// process
$category_sale_data = explode(',', $category->category_name);
foreach ($category_sale_data as $key => $value) {
list($sale_key, $sale_value) = explode('*', $value);
$category->sale_data[$sale_key][] = $sale_value;
//$category->sale_data_sum[$sale_key][] += $sale_value;
}
function sum($carry, $item)
{
$carry += array_values($item)[0];
return $carry;
}
$a = array_reduce(array_values($category->sale_data), "sum");
var_dump($a);
Or
<?php
// Sample data
$category = (object) ['category_name' => '32459*1500*lab*1,32460*400*lab*1,32461*600*lab*1'];
// process
$category_sale_data = explode(',', $category->category_name);
$category->sale_data_sum = null;
foreach ($category_sale_data as $key => $value) {
list($sale_key, $sale_value) = explode('*', $value);
$category->sale_data[$sale_key][] = $sale_value;
$category->sale_data_sum += $sale_value;
}
// display
print_r($category);
My array looks like the following:
Array
(
[0] => Array
(
[index] => 0
[quantity] => 1
[0] => Array
(
[id_product] => 20
[title] => Oranges
)
)
[1] => Array
(
[index] => 1
[quantity] => 1
[0] => Array
(
[id_product] => 24
[title] => Bananas
)
)
)
To make this array, this is my code:
$i = 0;
$content = array();
if(isset($_SESSION['cart'])){
foreach($_SESSION['cart'] as $result){
foreach($result as $item){
$values = $product->getById($item['id']);
if($values != null){ // which means it has product
/*
Checks if the array already contains that ID
this avoids duplicated products
*/
if(main::search_multidimensional($content, "id_product", $item['id_product']) == null){
$content[] = array("index" => $i, "quantity" => 1, $values);
$i++;
}else{ /*
in case it does have already the id_product in the array
I should update the "quantity" according to the "index".
*/
}
}
}
}
}
return $content;
My problem is after the }else{. I've been trying some codes without any success. I have to update the quantity according to the index. Although if you guys think there's a better alternative please let me know.
Edit: Since most of the people is worried about the search_multidimensional and it might be my solution, here's the function:
public function search_multidimensional($array, $key, $value){
$results = array();
if (is_array($array)) {
if (isset($array[$key]) && $array[$key] == $value) {
$results[] = $array;
}
foreach ($array as $subarray) {
$results = array_merge($results, self::search_multidimensional($subarray, $key, $value));
}
}
return $results;
}
EDIT 2:
In that case, would this help? (Since your search_multidimensional only returns a true or false)
$i = 0;
$content = array();
if(isset($_SESSION['cart'])){
foreach($_SESSION['cart'] as $result){
foreach($result as $item){
$values = $product->getById($item['id']);
if($values != null) { // which means it has product
/*
Checks if the array already contains that ID
this avoids duplicated products
*/
$product_exists = false;
foreach($content as &$cItem) {
if($cItem['values']['id_product'] == $item['id_product']) {
$cItem['values']['quantity']++; // Increments the quantity by 1
$product_exists = true;
break;
}
}
// If the product does not exist in $content, add it in.
if(!$product_exists)
$content[] = array("index" => $i, "quantity" => 1, "values" => $values);
$i++;
}
}
}
}
(Edited again to give an array key to $values)
OLD ANSWER:
Since you are recreating the cart array in $content, you could just do this in your else:
$content[] = array("index" => $i, "quantity" => $result['quantity'] + 1, $values);
Such that it would show like this:
$i = 0;
$content = array();
if(isset($_SESSION['cart'])){
foreach($_SESSION['cart'] as $result){
foreach($result as $item){
$values = $product->getById($item['id']);
if($values != null){ // which means it has product
/*
Checks if the array already contains that ID
this avoids duplicated products
*/
if(main::search_multidimensional($content, "id_product", $item['id_product']) == null)
$content[] = array("index" => $i, "quantity" => 1, $values);
else
$content[] = array("index" => $i, "quantity" => $result['quantity'] + 1, $values); // Retrieve current quantity and adds 1
$i++;
}
}
}
}
(I'm assuming you are only increasing the quantity by 1)
Solved.
All I had to do was to forget the $i variable, since it wasn't actually doing something necessary. Since I have id_product, which is unique I need to work with it.
if($values != null){ // Only if it has results
// checks if array already contains or not the product ID
// if does not have, it will add
if(global_::search_multidimensional($content, "id_product", $item['id_product']) == null){
$content[] = array("index" => $item['id_product'], "quantity" => 1, $values);
// index is now the id of the product
}else{
// otherwise, loop all the elements and add +1
foreach($content as $key => $result){
if($item['id_product'] == $content[$key]['index']){
$content[$key]['quantity']++;
}
}
}
}
As your $content array has fixed structure (fixed number of levels) you don't need to use recursive function. Your search_multidimensional function could be much simpler. And it should return index of found element (if any) in the array:
function search_multidimensional($array, $key, $value) {
foreach ($array as $i => $el) {
foreach ($el as $j => $v) {
if (is_int($j) && isset($v[$key]) && $v[$key] == $value) return $i;
}
}
return false;
}
So the snippet building $content should be changed like this:
...
if (($index = search_multidimensional($content, "id_product", $item['id_product'])) === false) {
$content[] = array("index" => $i, "quantity" => 1, $values); $i++;
}
else {
$content[$index]['quantity']++;
}
I want to dissect an array like this:
[
"ID",
"UUID",
"pushNotifications.sent",
"campaigns.boundDate",
"campaigns.endDate",
"campaigns.pushMessages.sentDate",
"pushNotifications.tapped"
]
To a format like this:
{
"ID" : 1,
"UUID" : 1,
"pushNotifications" :
{
"sent" : 1,
"tapped" : 1
},
"campaigns" :
{
"boundDate" : 1,
"endDate" : 1,
"pushMessages" :
{
"endDate" : 1
}
}
}
It would be great if I could just set a value on an associative array in a keypath-like manner:
//To achieve this:
$dissected['campaigns']['pushMessages']['sentDate'] = 1;
//By something like this:
$keypath = 'campaigns.pushMessages.sentDate';
$dissected{$keypath} = 1;
How to do this in PHP?
You can use :
$array = [
"ID",
"UUID",
"pushNotifications.sent",
"campaigns.boundDate",
"campaigns.endDate",
"campaigns.pushMessages.sentDate",
"pushNotifications.tapped"
];
// Build Data
$data = array();
foreach($array as $v) {
setValue($data, $v, 1);
}
// Get Value
echo getValue($data, "campaigns.pushMessages.sentDate"); // output 1
Function Used
function setValue(array &$data, $path, $value) {
$temp = &$data;
foreach(explode(".", $path) as $key) {
$temp = &$temp[$key];
}
$temp = $value;
}
function getValue($data, $path) {
$temp = $data;
foreach(explode(".", $path) as $ndx) {
$temp = isset($temp[$ndx]) ? $temp[$ndx] : null;
}
return $temp;
}
function keyset(&$arr, $keypath, $value = NULL)
{
$keys = explode('.', $keypath);
$current = &$arr;
while(count($keys))
{
$key = array_shift($keys);
if(!isset($current[$key]) && count($keys))
{
$current[$key] = array();
}
if(count($keys))
{
$current = &$current[$key];
}
}
$current[$key] = $value;
}
function keyget($arr, $keypath)
{
$keys = explode('.', $keypath);
$current = $arr;
foreach($keys as $key)
{
if(!isset($current[$key]))
{
return NULL;
}
$current = $current[$key];
}
return $current;
}
//Testing code:
$r = array();
header('content-type: text/plain; charset-utf8');
keyset($r, 'this.is.path', 39);
echo keyget($r, 'this.is.path');
var_dump($r);
It's a little rough, I can't guarantee it functions 100%.
Edit: At first you'd be tempted to try to use variable variables, but I've tried that in the past and it doesn't work, so you have to use functions to do it. This works with some limited tests. (And I just added a minor edit to remove an unnecessary array assignment.)
In the meanwhile, I came up with (another) solution:
private function setValueForKeyPath(&$array, $value, $keyPath)
{
$keys = explode(".", $keyPath, 2);
$firstKey = $keys[0];
$remainingKeys = (count($keys) == 2) ? $keys[1] : null;
$isLeaf = ($remainingKeys == null);
if ($isLeaf)
$array[$firstKey] = $value;
else
$this->setValueForKeyPath($array[$firstKey], $value, $remainingKeys);
}
Sorry for the "long" namings, I came from the Objective-C world. :)
So calling this on each keyPath, it actually gives me the output:
fields
Array
(
[0] => ID
[1] => UUID
[2] => pushNotifications.sent
[3] => campaigns.boundDate
[4] => campaigns.endDate
[5] => campaigns.pushMessages.endDate
[6] => pushNotifications.tapped
)
dissectedFields
Array
(
[ID] => 1
[UUID] => 1
[pushNotifications] => Array
(
[sent] => 1
[tapped] => 1
)
[campaigns] => Array
(
[boundDate] => 1
[endDate] => 1
[pushMessages] => Array
(
[endDate] => 1
)
)
)
I am wondering if I could explain this.
I have a multidimensional array , I would like to get the count of particular value appearing in that array
Below I am showing the snippet of array . I am just checking with the profile_type .
So I am trying to display the count of profile_type in the array
EDIT
Sorry I've forgot mention something, not something its the main thing , I need the count of profile_type==p
Array
(
[0] => Array
(
[Driver] => Array
(
[id] => 4
[profile_type] => p
[birthyear] => 1978
[is_elite] => 0
)
)
[1] => Array
(
[Driver] => Array
(
[id] => 4
[profile_type] => d
[birthyear] => 1972
[is_elite] => 1
)
)
)
Easy solution with RecursiveArrayIterator, so you don't have to care about the dimensions:
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
$counter = 0
foreach ($iterator as $key => $value) {
if ($key == 'profile_type' && $value == 'p') {
$counter++;
}
}
echo $counter;
Something like this might work...
$counts = array();
foreach ($array as $key=>$val) {
foreach ($innerArray as $driver=>$arr) {
$counts[] = $arr['profile_type'];
}
}
$solution = array_count_values($counts);
I'd do something like:
$profile = array();
foreach($array as $elem) {
if (isset($elem['Driver']['profile_type'])) {
$profile[$elem['Driver']['profile_type']]++;
} else {
$profile[$elem['Driver']['profile_type']] = 1;
}
}
print_r($profile);
You may also use array_walk($array,"test") and define a function "test" that checks each item of the array for 'type' and calls recursively array_walk($arrayElement,"test") for items of type 'array' , else checks for the condition. If condition satisfies, increment a count.
Hi You can get count of profuke_type==p from a multi dimensiona array
$arr = array();
$arr[0]['Driver']['id'] = 4;
$arr[0]['Driver']['profile_type'] = 'p';
$arr[0]['Driver']['birthyear'] = 1978;
$arr[0]['Driver']['is_elite'] = 0;
$arr[1]['Driver']['id'] = 4;
$arr[1]['Driver']['profile_type'] = 'd';
$arr[1]['Driver']['birthyear'] = 1972;
$arr[1]['Driver']['is_elite'] = 1;
$arr[2]['profile_type'] = 'p';
$result = 0;
get_count($arr, 'profile_type', 'd' , $result);
echo $result;
function get_count($array, $key, $value , &$result){
if(!is_array($array)){
return;
}
if($array[$key] == $value){
$result++;
}
foreach($array AS $arr){
get_count($arr, $key, $value , $result);
}
}
try this..
thanks
In an array such as the one below, how could I rename "fee_id" to "id"?
Array
(
[0] => Array
(
[fee_id] => 15
[fee_amount] => 308.5
[year] => 2009
)
[1] => Array
(
[fee_id] => 14
[fee_amount] => 308.5
[year] => 2009
)
)
foreach ( $array as $k=>$v )
{
$array[$k] ['id'] = $array[$k] ['fee_id'];
unset($array[$k]['fee_id']);
}
This should work
You could use array_map() to do it.
$myarray = array_map(function($tag) {
return array(
'id' => $tag['fee_id'],
'fee_amount' => $tag['fee_amount'],
'year' => $tag['year']
); }, $myarray);
$arrayNum = count($theArray);
for( $i = 0 ; $i < $arrayNum ; $i++ )
{
$fee_id_value = $theArray[$i]['fee_id'];
unset($theArray[$i]['fee_id']);
$theArray[$i]['id'] = $fee_id_value;
}
This should work.
Copy the current 'fee_id' value to a new key named 'id' and unset the previous key?
foreach ($array as $arr)
{
$arr['id'] = $arr['fee_id'];
unset($arr['fee_id']);
}
There is no function builtin doing such thin afaik.
This is the working solution, i tested it.
foreach ($myArray as &$arr) {
$arr['id'] = $arr['fee_id'];
unset($arr['fee_id']);
}
The snippet below will rename an associative array key while preserving order (sometimes... we must). You can substitute the new key's $value if you need to wholly replace an item.
$old_key = "key_to_replace";
$new_key = "my_new_key";
$intermediate_array = array();
while (list($key, $value) = each($original_array)) {
if ($key == $old_key) {
$intermediate_array[$new_key] = $value;
}
else {
$intermediate_array[$key] = $value;
}
}
$original_array = $intermediate_array;
Converted 0->feild0, 1->field1,2->field2....
This is just one example in which i get comma separated value in string and convert it into multidimensional array and then using foreach loop i changed key value of array
<?php
$str = "abc,def,ghi,jkl,mno,pqr,stu
abc,def,ghi,jkl,mno,pqr,stu
abc,def,ghi,jkl,mno,pqr,stu
abc,def,ghi,jkl,mno,pqr,stu;
echo '<pre>';
$arr1 = explode("\n", $str); // this will create multidimensional array from upper string
//print_r($arr1);
foreach ($arr1 as $key => $value) {
$arr2[] = explode(",", $value);
foreach ($arr2 as $key1 => $value1) {
$i =0;
foreach ($value1 as $key2 => $value2) {
$key3 = 'field'.$i;
$i++;
$value1[$key3] = $value2;
unset($value1[$key2]);
}
}
$arr3[] = $value1;
}
print_r($arr3);
?>
I wrote a function to do it using objects or arrays (single or multidimensional) see at https://github.com/joaorito/php_RenameKeys.
Bellow is a simple example, you can use a json feature combine with replace to do it.
// Your original array (single or multi)
$original = array(
'DataHora' => date('YmdHis'),
'Produto' => 'Produto 1',
'Preco' => 10.00,
'Quant' => 2);
// Your map of key to change
$map = array(
'DataHora' => 'Date',
'Produto' => 'Product',
'Preco' => 'Price',
'Quant' => 'Amount');
$temp_array = json_encode($original);
foreach ($map AS $k=>$v) {
$temp_array = str_ireplace('"'.$k.'":','"'.$v.'":', $temp);
}
$new_array = json_decode($temp, $array);
Multidimentional array key can be changed dynamically by following function:
function change_key(array $arr, $keySetOrCallBack = [])
{
$newArr = [];
foreach ($arr as $k => $v) {
if (is_callable($keySetOrCallBack)) {
$key = call_user_func_array($keySetOrCallBack, [$k, $v]);
} else {
$key = $keySetOrCallBack[$k] ?? $k;
}
$newArr[$key] = is_array($v) ? array_change_key($v, $keySetOrCallBack) : $v;
}
return $newArr;
}
Sample Example:
$sampleArray = [
'hello' => 'world',
'nested' => ['hello' => 'John']
];
//Change by difined key set
$outputArray = change_key($sampleArray, ['hello' => 'hi']);
//Output Array: ['hi' => 'world', 'nested' => ['hi' => 'John']];
//Change by callback
$outputArray = change_key($sampleArray, function($key, $value) {
return ucwords(key);
});
//Output Array: ['Hello' => 'world', 'Nested' => ['Hello' => 'John']];
I have been trying to solve this issue for a couple hours using recursive functions, but finally I realized that we don't need recursion at all. Below is my approach.
$search = array('key1','key2','key3');
$replace = array('newkey1','newkey2','newkey3');
$resArray = str_replace($search,$replace,json_encode($array));
$res = json_decode($resArray);
On this way we can avoid loop and recursion.
Hope It helps.