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;
}
Related
This is almost similar to my other question which is related to the same project I'm working on.. Link to my other question
but in this case the array is different as follow:
Array
(
[2014-08-01 11:27:03] => 2
[2014-08-01 11:52:57] => 2
[2014-08-01 11:54:49] => 2
[2014-08-02 11:59:54] => 4
[2014-08-02 12:02:41] => 2
[2014-08-05 12:09:38] => 4
[2014-08-07 12:23:12] => 3
[2014-08-07 12:25:18] => 3
// and so on...
)
That is my output array and in order to get that array I had to do some miracles... anyway, so based on that array I have to sum the value for each key date and build an array something like this...
Array
(
[2014-08-01] => 6
[2014-08-02] => 6
[2014-08-05] => 4
[2014-08-07] => 6
// and so on...
)
That last array will be use to build graphs with morrisonJS, what I have is this:
$res_meno = array();
foreach ($sunArr as $keys => $values) {
$arrays= explode(" ",$sumArr[$keys]);
$res_meno[] = $arrays[0];
}
$vals_char2 = array_count_values($res_meno);
That is my attempt to build my last array but is not working...
any help would be greatly appreciated!
Thank you for taking the time.
Try this code
<?php
$arr = array(
"2014-08-01 11:27:03" => 2,
"2014-08-01 11:52:57" => 2,
"2014-08-01 11:54:49" => 2,
"2014-08-02 11:59:54" => 4,
"2014-08-02 12:02:41" => 2,
"2014-08-05 12:09:38" => 4,
"2014-08-07 12:23:12" => 3,
"2014-08-07 12:25:18" => 3
);
$new_array = array();
foreach($arr as $k => $v){
$date = reset(explode(" ", $k));
if(isset($new_array[$date])){
$new_array[$date] += $v;
}
else{
$new_array[$date] = $v;
}
}
print_r($new_array);
?>
DEMO
$sunArr = array
(
"2014-08-01 11:27:03" => 2,
"2014-08-01 11:52:57" => 2,
"2014-08-01 11:54:49" => 2,
"2014-08-02 11:59:54" => 4,
"2014-08-02 12:02:41" => 2,
"2014-08-05 12:09:38" => 4,
"2014-08-07 12:23:12" => 3,
"2014-08-07 12:25:18" => 3,
);
$res_meno = array();
foreach ($sunArr as $keys => $values) {
$arrays= explode(" ",$keys);
if(isset($res_meno[$arrays[0]]))
{
$res_meno[$arrays[0]] = $res_meno[$arrays[0]] + $values;
}
else
{
$res_meno[$arrays[0]] = $values;
}
}
print_r($res_meno);
exit;
Try this, i think it might fix the problem
Try this PHP Code You Can test here
$sunArr = Array
(
'2014-08-01 11:27:03' => 2,
'2014-08-01 11:52:57' => 2,
'2014-08-01 11:54:49' => 2,
'2014-08-02 11:59:54' => 4,
'2014-08-02 12:02:41' => 2,
'2014-08-05 12:09:3' => 4,
'2014-08-07 12:23:12' => 3,
'2014-08-07 12:25:18' => 3
);
$key = 0;
$res_meno = array();
foreach ($sunArr as $keys => $values)
{
$ar= explode(" ", $keys);
if( $key == $ar[0] )
{
$res_meno[$key] = $sunArr[$keys] + $res_meno[$key];
}
else
{
$key = $ar[0];
$res_meno[$key] = $values;
}
}
echo '<pre>';
print_r($res_meno);
die;
Where does the first array come from? If it's from a SQL database, it's better to create a query that returns the aggregated array.
Otherwise no need to use array_key_values for that:
$res_meno = array();
foreach ($sumArr as $keys => $values) {
$key = substr($keys, 0, 10);
$res_meno[$key] = (empty($res_meno[$key]) ? 0 : $res_meno[$key]) + $values;
}
Here is a solution which uses a callback. Not to use loops is often better!
$sunArr = array(
'2014-08-01 11:27:03' => 3,
'2014-08-01 11:27:05' => 5,
'2013-09-01 11:01:05' => 1
);
$res = array();
function map($item, $key, &$result)
{
$result[current(explode(" ", $key))] += $item;
}
array_walk($sunArr, "map", &$res);
var_dump($res);
You can test it here on codepad.
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);
?>
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>';
?>
I have an array like this:
$months = Array (
"may" =>
Array (
"A" => 101,
"B" => 33,
"C" => 25
),
"june" =>
Array (
"A" => 73,
"B" => 11,
"D" => 32
),
"july" =>
Array (
"A" => 45,
"C" => 12
)
);
I want to get an array like this:
Array ( ['all'] =>
Array (
[A] => 219
[B] => 44
[C] => 37
[D] => 32
)
)
I wrote a function with 2 parameters (the two arrays to join) and it worked, but I fail, when I try to make it possible to call it with more than 2 arrays. I tried to do it via recursion:
function array_merge_elements(){
$arg_list = func_get_args();
$array1 = $arg_list[0];
$array2 = $arg_list[1];
$keys = array_unique(array_merge(array_keys($array1), array_keys($array2)));
$result_array = array();
foreach($keys as $key) {
$result_array["$key"] = 0;
if(!empty($array1[$key])) {
$result_array["$key"] += $array1[$key];
}
if(!empty($array2[$key])) {
$result_array["$key"] += $array2[$key];
}
}
if(func_num_args() == 2) {
return $result_array;
} else {
unset($arg_list[0]);
unset($arg_list[1]);
return array_merge_elements($result_array, $arg_list);
}
}
The problem seems to be, that calling the function with (array1, arglist) is not the same as calling the function with (array1, array2, array3) etc.
What's wrong with just doing (demo)
foreach ($months as $month) {
foreach ($month as $letter => $value) {
if (isset($months['all'][$letter])) {
$months['all'][$letter] += $value;
} else {
$months['all'][$letter] = $value;
}
}
}
print_r($months['all']);
or - somewhat less readable due to the ternary operation (demo):
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($months));
foreach ($iterator as $letter => $value) {
isset($months['all'][$letter])
? $months['all'][$letter] += $value
: $months['all'][$letter] = $value;
}
print_r($months['all']);
If you'd split off the first two entries of your found arguments; you can use the resulting array in a call with this function: Call_user_func_array
for fellow googlers out there, here's the answer to the original question
Assume we have a function that adds two arrays together:
function array_plus($a, $b) {
foreach($b as $k => $v)
$a[$k] = (isset($a[$k]) ? $a[$k] : 0) + $v;
return $a;
}
this is how to apply this function to a set of arrays
$sum = array_reduce($months, 'array_plus', array());
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.