I have an array like below, and I want to do the total of values in a specific manner where all values of ADDED_NEW_(.*) {regular expressions}, and similarly other values.
I have only specific vals like ADDED_NEW, ADDED_OLD, and ADD_LATER.
My array is like:
$stats = Array
(
[ADDED_NEW_2012_06_12] => 16
[ADDED_OLD_2012_06_12] => 10
[ADD_LATER_2012_06_12] => 12
[ADDED_NEW_2012_06_11] => 16
[ADDED_OLD_2012_06_11] => 10
[ADD_LATER_2012_06_11] => 12
)
Can you please tell me how can i obtain my result. I don't know how to add such values using regex in php. Please help.
The output I am expecting is $ADDED_NEW = 32 (i.e. 16+16), $ADDED_OLD = 20 (i.e. 10+10) and $ADD_LATER = 24 (i.e. 12+12)
I believe you just want to add values of similar keys in which they all start with ADDED_NEW or ADDED_OLD or ADD_LATER I assume so we can just make 3 counters and just match for those in the key and add to the counters.
I don't know much PHP but using manuals and my knowledge from Python, this is what I mustered up:
<?php
$ADDED_NEW = 0;
$ADDED_OLD = 0;
$ADD_LATER = 0;
foreach ($stats as $key => $value) {
if (preg_match("ADDED_NEW_.*", $key)) { $ADDED_NEW += $value; }
if (preg_match("ADDED_OLD_.*", $key)) { $ADDED_OLD += $value; }
if (preg_match("ADD_LATER_.*", $key)) { $ADD_LATER += $value; }
}
?>
check this out.
<?php
$stats = array(
'ADDED_NEW_2012_06_12' => 16,
'ADDED_OLD_2012_06_12' => 10,
'ADD_LATER_2012_06_12' => 12,
'ADDED_NEW_2012_06_11' => 16,
'ADDED_OLD_2012_06_11' => 10,
'ADD_LATER_2012_06_11' => 12
);
$ADDED_NEW = 0;
$ADDED_OLD = 0;
$ADD_LATER = 0;
foreach ($stats as $key => $value) {
if (preg_match("/ADDED_NEW_.*/", $key)) { $ADDED_NEW += $value; }
else if (preg_match("/ADDED_OLD_.*/", $key)) { $ADDED_OLD += $value; }
else if (preg_match("/ADD_LATER_.*/", $key)) { $ADD_LATER += $value; }
}
echo "$ADDED_NEW - $ADDED_OLD - $ADD_LATER";
?>
outputs:
32 - 20 - 24
Try this:
<?php
$stats = array
(
"ADDED_NEW_2012_06_12" => 16,
"ADDED_OLD_2012_06_12" => 10,
"ADD_LATER_2012_06_12" => 12,
"ADDED_NEW_2012_06_11" => 16,
"ADDED_OLD_2012_06_11" => 10,
"ADD_LATER_2012_06_11" => 12,
);
$accumulators = array
(
"ADDED_NEW" => 0,
"ADDED_OLD" => 0,
"ADD_LATER" => 0,
);
foreach($stats as $key => $value)
{
foreach(array_keys($accumulators) as $accumulator)
{
if(preg_match("#^${accumulator}#m", $key)){$accumulators[$accumulator] += $value;}
}
}
header('Content-Type: text/plain');
print_r($accumulators);
?>
Related
I have a question about how to make an iteration. I want to place a total row after each item in the array if the next element in the array matches a specific condition. Spesific conditions have logic like this
the data like this
if i request a qty for example = 60 the result i hope like this
you can see
data[2] = 01/03/2020 just took 10 out of 40
$iter = new \ArrayIterator($values);
$sum = 0;
foreach($values as $key => $value) {
$nextValue = $iter->current();
$iter->next();
$nextKey = $iter->key();
if(condition) {
$sum += $value;
}
}
dd($iter);
how to make this logic work on php language/ laravel?
Following logic might help you on your way:
<?php
$stock = [
'01/01/2020' => 20,
'01/02/2020' => 30,
'01/03/2020' => 40
];
showStatus($stock, 'in stock - before transaction');
$demand = 60;
foreach ($stock as $key => $value) {
if ($value <= $demand) {
$stock[$key] = 0;
$supplied[$key] = $value;
$demand -= $value;
} else {
$stock[$key] -= $demand;
$supplied[$key] = $value - ($value - $demand);
$demand = 0;
}
}
showStatus($supplied, 'supplied');
showStatus($stock, 'in stock - after transaction');
function showStatus($arr = [], $msg = '')
{
echo $msg;
echo '<pre>';
print_r($arr);
echo '</pre>';
}
?>
**Output:**
in stock - before transaction
Array
(
[01/01/2020] => 20
[01/02/2020] => 30
[01/03/2020] => 40
)
supplied
Array
(
[01/01/2020] => 20
[01/02/2020] => 30
[01/03/2020] => 10
)
in stock - after transaction
Array
(
[01/01/2020] => 0
[01/02/2020] => 0
[01/03/2020] => 30
)
Working demo
I'm not sure I've understood you correctly but this might help:
$values = [
'01/01/2020' => 20,
'01/02/2020' => 30,
'01/03/2020' => 40
];
$demand = 60;
$total = array_sum($values);
$decrease = $total - $demand; //(20+30+40) - 60 = 30
$last_key = array_keys($values,end($values))[0]; //Is 01/03/2020 in this case
$values[$last_key] -= $decrease; //Decrease value with 30 calulated above
Would output:
Array
(
[01/01/2020] => 20
[01/02/2020] => 30
[01/03/2020] => 10
)
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;
}
}
For a rent application, I have an array $dates like this:
Array
(
[2013-07-19] => 1
[2013-07-21] => 3
[2013-07-23] => 2
[2013-07-24] => 4
[2013-07-25] => 4
[2013-07-26] => 2
[2013-07-27] => 2
[2013-07-30] => 3
[2013-07-31] => 1
)
The date is the key, and the values are the number of items rent in that day for a specific product
How can I split this array in many sub arrays containing each a list of consecutive days?
Like this:
Array
(
[0] => Array
(
[2013-07-19] => 1
)
[1] => Array
(
[2013-07-21] => 3
)
[2] => Array
(
[2013-07-23] => 2
[2013-07-24] => 4
[2013-07-25] => 4
[2013-07-26] => 2
[2013-07-27] => 2
)
[3] => Array
(
[2013-07-30] => 3
[2013-07-31] => 1
)
)
$newArray = array();
foreach ($array as $date => $value)
{
// Make sure the newArray starts off with at least one element
if (empty($newArray))
$newArray[] = array();
// Calculate the difference in dates.
// (I like using DateTime, but use whichever method you like)
$dateTime = new DateTime($date);
$lastDateTime = new DateTime($lastDate);
$dateDiff = $dateTime->diff($lastDateTime);
// Add a new array to the end if the difference between this element and the last was more than a day
if ($dateDiff->days > 1)
$newArray[] = array();
// We can now be guaranteed that the last element of $newArray is the one we want to append to
$newArray[count($newArray) - 1][$date] = $value;
// Keep track of the last date you saw
$lastDate = $date;
}
Here it is in action: https://eval.in/38039
$newArray = array();
$i = 0;
foreach ($array as $date => $key) {
$thisDay = end(explode('-', $date));
$nextDay = end(explode('-', next($array[$date])));
if ($thisDay + 1 != $nextDay + 0)
$i++;
if (!isset($newArray[$i])) {
$newArray[$i] = array($date => $key);
} else {
if (!isset($newArray[$i][$date])) {
$newArray[$i][$date] = $key;
} else {
$newArray[$i][$date] = $key;
}//END IF
}//END IF
}//END FOREACH LOOP
This is the code i would use to do what you are asking.
UPDATE:
I was wrong above. i have altered the code to work this time:
$newArray = array();
$i = 0;
foreach ($array as $date => $key) {
$thisDay = end(explode('-', $date));
$nextDay = array_key_exists(date('Y-m-d', strtotime($date . ' +1 day')), $array);
if (!isset($newArray[$i])) {
$newArray[$i] = array($date => $key);
} else {
if (!isset($newArray[$i][$date])) {
$newArray[$i][$date] = $key;
} else {
$newArray[$i][$date] = $key;
}//END IF
}//END IF
if (!$nextDay)
$i++;
}//END FOREACH LOOP
Here is my test case:
<?php
$array = array(
'2013-07-19' => 1,
'2013-07-21' => 3,
'2013-07-23' => 2,
'2013-07-24' => 4,
'2013-07-25' => 4,
'2013-07-26' => 2,
'2013-07-27' => 2,
'2013-07-30' => 3,
'2013-07-31' => 1
);
echo '<pre>' . print_r($array, true) . '</pre>';
$newArray = array();
$i = 0;
foreach ($array as $date => $key) {
$thisDay = end(explode('-', $date));
$nextDay = array_key_exists(date('Y-m-d', strtotime($date . ' +1 day')), $array);
if (!isset($newArray[$i])) {
$newArray[$i] = array($date => $key);
} else {
if (!isset($newArray[$i][$date])) {
$newArray[$i][$date] = $key;
} else {
$newArray[$i][$date] = $key;
}//END IF
}//END IF
if (!$nextDay)
$i++;
}//END FOREACH LOOP
echo '<pre>' . print_r($newArray, true) . '</pre>';
?>
you can do it like this:
$data = array(
'2013-07-19' => 1,
'2013-07-21' => 3,
'2013-07-23' => 2,
'2013-07-24' => 4,
'2013-07-25' => 4,
'2013-07-26' => 2,
'2013-07-27' => 2,
'2013-07-30' => 3,
'2013-07-31' => 1
);
$result = array();
$ref = new DateTime('1821-11-11');
foreach ($data as $datum => $nb) {
if ($ref->add(new DateInterval('P1D'))->format('Y-m-d')!=$datum) {
$result[] = array();
$ref = new DateTime($datum);
}
$result[array_pop(array_keys($result))][$datum] = $nb;
}
print_r($result);
I have an array like below, and I want to do the total of values in a spefic manner where all values of val1_(.*) {regular expressions}, and similarly other values.
I have only specific vals like val1, val2, and val3.
My array is like:
$stats = Array
(
[ADDED_NEW_2012_06_12] => 16
[ADDED_OLD_2012_06_12] => 10
[ADD_LATER_2012_06_12] => 12
[ADDED_NEW_2012_06_11] => 16
[ADDED_OLD_2012_06_11] => 10
[ADD_LATER_2012_06_11] => 12
)
Can you please tell me how can i obtain my result. I don't know how to add such values using regex in php. Please help.
You don't necessarily need a regular expression if you can identify the values by the first part of the key.
Iterate over the array and create a new array with one element for each valX:
$totals = array();
// iterate over the array
foreach($array as $key => $value) {
$k = substr($key, 0, strpos($key, '_')); // get the first part (i.e. `valX`)
if(!isset($totals[$k])) { // if $totals['valX'] does not exist, initialize
$totals[$k] = 0;
}
$totals[$k] += $value; // sum
}
Reference: foreach, substr, strpos, isset
Do you mean this?
$array = array (
'val1_2012_06_12' => 16,
'val2_2012_06_12' => 10,
'val3_2012_06_12' => 12,
'val1_2012_06_11' => 16,
'val2_2012_06_11' => 10,
'val3_2012_06_11' => 12,
);
$sums = array();
foreach ($array as $key => $value) {
$regex = '~(?P<prefix>val\d+)_\d{4}_\d{2}_\d{2}~';
if (preg_match($regex, $key, $matches)) {
$sums[$matches['prefix']] += $value;
}
}
It will produce something like this, it will group sums by prefixes:
Array
(
[val1] => 32
[val2] => 20
[val3] => 24
)
Edit: updated to the refined question
You can match the key against a code, and create a sum from there like this with a simple foreach loop.
$array = array(
'ADDED_NEW_2012_06_12' => 16,
'ADDED_OLD_2012_06_12' => 10,
'ADD_LATER_2012_06_12' => 12,
'ADDED_NEW_2012_06_11' => 16,
'ADDED_OLD_2012_06_11' => 10,
'ADD_LATER_2012_06_11' => 12,
);
$sumarray = array();
foreach ($array as $key => $value)
{
$matches = array();
preg_match("/^(\w+?_\w+?)_/i", $key, $matches);
$key = $matches[1];
if (!isset($sumarray[$key]))
{
$sumarray[$key] = $value;
} else {
$sumarray[$key] = $sumarray[$key] + $value;
}
}
print_r($sumarray);
if you have just this tree type of value in array so you can use this:
$stats = Array(
'ADDED_NEW_2012_06_12' => 16,
'ADDED_OLD_2012_06_12' => 10,
'ADD_LATER_2012_06_12' => 12,
'ADDED_NEW_2012_06_11' => 16,
'ADDED_OLD_2012_06_11' => 10,
'ADD_LATER_2012_06_11' => 12
);
foreach($stats as $key => $value)
{
$substring=substr($key, 0 , 9);
if($substring=='ADDED_NEW')
#$ADDED_NEW += $value;
elseif($substring=='ADDED_OLD')
#$ADDED_OLD += $value;
else
#$ADD_LATER += $value;
}
echo 'ADDED_NEW : ' . $ADDED_NEW .'<br>ADDED_OLD : ' . $ADDED_OLD .'<br>ADD_LATER : ' . $ADD_LATER ;
Output :
ADDED_NEW : 32
ADDED_OLD : 20
ADD_LATER : 24
$sum = 0;
Foreach($object as $key=>$value){
$sum += $value;
}
I'm working on a leader board that pulls the top scorers into first, second, and third place based on points. Right now I'm working with a sorted array that looks like this (but could be of infinite length with infinite point values):
$scores = Array
(
["bob"] => 20
["Jane"] => 20
["Jill"] => 15
["John"] => 10
["Jacob"] => 5
)
I imagine I could use a simple slice or chunk, but I'd like to allow for ties, and ignore any points that don't fit into the top three places, like so:
$first = Array
(
["bob"] => 20
["Jane"] => 20
)
$second = Array
(
["Jill"] => 15
)
$third = Array
(
["John"] => 10
)
Any ideas?
$arr = array(
"Jacob" => 5,
"bob" => 20,
"Jane" => 20,
"Jill" => 15,
"John" => 10,
);
arsort($arr);
$output = array();
foreach($arr as $name=>$score)
{
$output[$score][$name] = $score;
if (count($output)>3)
{
array_pop($output);
break;
}
}
$output = array_values($output);
var_dump($output);
$first will be in $output[0], $second in $output[1] and so on.. Code is limited to 3 first places.
ps: updated to deal with tie on the third place
I would do something like:
function chunk_top_n($scores, $limit)
{
arsort($scores);
$current_score = null;
$rank = array();
$n = 0;
foreach ($scores as $person => $score)
{
if ($current_score != $score)
{
if ($n++ == $limit) break;
$current_score = $score;
$rank[] = array();
$p = &$rank[$n - 1];
}
$p[$person] = $score;
}
return $rank;
}
It sorts the array, then creates numbered groups. It breaks as soon as the limit has been reached.
You can do it with less code if you use the score as the key of the array, but the benefit of the above approach is it creates the array exactly how you want it the first time through.
You could also pass $scores by reference if you don't mind the original getting sorted.
Here's my go at it:
<?php
function array_split_value($array)
{
$result = array();
$indexes = array();
foreach ($array as $key => $value)
{
if (!in_array($value, $indexes))
{
$indexes[] = $value;
$result[] = array($key => $value);
}
else
{
$index_search = array_search($value, $indexes);
$result[$index_search] = array_merge($result[$index_search], array($key => $value));
}
}
return $result;
}
$scores = Array(
'bob' => 20,
'Jane' => 20,
'Jill' => 15,
'John' => 10,
'Jacob' => 5
);
echo '<pre>';
print_r(array_split_value($scores));
echo '</pre>';
?>