I have a code that I am trying to make work but I just can't!
I have 2 arrays: 1-> Diares 2-> The value corresponds to each diary entry.
$diarioNum = array( [0] => 1 [1] => 2 [2] => 1 [3] => 3 [4] => 5 [5] => 1 [6] => 1 );
$vintoBookSX = array( [0] => -0.5 [1] => -0.4 [2] => -0.6 [3] => -0.4 [4] => -0.4 [5] => -1 [6] => -1 );
In my case I have multiply diaries and in the database from which I extrapolate the data are not in order, so I had to do this code:
<?php
$con = array_count_values($diarioNum);
foreach ($con as $key => $value) {
$pos = array_keys($diarioNum, $key);
echo "Diario " .$key. "<br>";
foreach ($pos as $ke => $val) {
$vBKsx = $vintoBookSX[$val];
echo $vBKsx . "<br>";
}
}
?>
Output:
Diario 1
-0.5
-0.6
-1
-1
Diario 2
-0.4
Diario 3
-0.4
Diario 5
-0.4
my Database table:
my Database table
Now I have to sum values for each diary.
And then output it must be:
Diario 1
-3.1
Diario 2
-0.4
Diario 3
-0.4
Diario 5
-0.4
Can you help me please?
You seem to use a complicated way to do that, this is how I will do it (on PHP side):
$diarioNum = [ 1, 2, 1, 3, 5, 1, 1 ];
$vintoBookSX = [ -0.5, -0.4, -0.6, -0.4, -0.4, -1, -1 ];
$result = [];
foreach ($diarioNum as $k => $day) {
$result[$day][] = $vintoBookSX[$k];
}
print_r($result);
$sums = array_map('array_sum', $result);
print_r($sums);
demo
There's probably a better way to do it on DBMS side. Something like:
SELECT diarioNumero, SUM(VintoBook_SX)
FROM yourtable
GROUP BY diarioNumero
ORDER BY diarioNumero
Here is one more solution
$diarioNum = array(1, 2, 1, 3, 5, 1, 1 );
$vintoBookSX = array(-0.5, -0.4, -0.6, -0.4, -0.4, -1, -1 );
$result = array_fill_keys( array_unique($diarioNum), 0);
foreach ( $diarioNum as $key => $val ) {
$result[ $val ] += $vintoBookSX[ $key ];
}
foreach ( $result as $key => $val ) {
echo "Diario $key <br>";
echo $val . "<br>";
}
Related
I have an array in PHP.
For example :
Array
(
[3] => 6
[2] => 4
[1] => 2
[4] => 8
[6] => 12
)
I need to shift the position of each value to the next index.
ie, The desired output is
Array
(
[3] => 12
[2] => 6
[1] => 4
[4] => 2
[6] => 8
)
I need to keep the keys unchanged and round shift the values.
Which is the simplest method to attain it?
What I already tried is
$lastValue = $array[array_keys($array)[4]];
$firstKey = array_keys($array)[0];
for ($i=4; $i>0; $i--) {
$array[array_keys($array)[$i]] = $array[array_keys($array)[$i-1]];
}
$array[$firstKey] = $lastValue;
print_r($array);
php is so coool ^_^
part of the idea ~stolen~ taken from #Peters solution, sorry, mate :)
<?php
$array =
[
3 => 6,
2 => 4,
1 => 2,
4 => 8,
6 => 12,
];
$newArray = array_combine(array_keys($array), array_merge([array_pop($array)], $array));
var_dump($newArray);
demo
You can do a round shift on the value. Demo
$array =
[
3 => 6,
2 => 4,
1 => 2,
4 => 8,
6 => 12,
];
$values = [null];
$keys = [];
foreach($array as $k => $v){
$keys[] = $k;
$values[] = $v;
}
$values[0] = $v;
array_pop($values);
$result = array_combine($keys,$values);
print_r($result);
I need to sum the values in element 1 of my array where the values in element 0 are duplicate.
Here's a small piece of my array
Array
(
[0] => 3
[1] => 1
)
Array
(
[0] => 3
[1] => 2
)
Array
(
[0] => 3
[1] => 128
)
Array
(
[0] => 39
[1] => 4
)
The results i'm expecting to see
Array
(
[0] => 3
[1] => 131
)
Array
(
[0] => 39
[1] => 4
)
I'm still really new to PHP so any help is greatly appreciated.
You can use a combination of array_intersect, array_column and array_sum to only iterate twice. (One for each unique column 0 value).
$col0 = array_column($arr, 0);
$col1 = array_column($arr, 1);
Foreach(array_unique($col0) as $val){
$res[] = [$val, array_sum(array_intersect_key($col1, array_intersect($col0,[$val])))];
}
Var_dump($res);
https://3v4l.org/gKb5b
The way I've done it is made sure all duplicates where put in the same array.
// Your data
$sample = [[3, 1],[3, 2],[3, 128],[39, 4]];
foreach($sample as $array){
$tmp[$array[0]][] = $array[1];
}
# Output: {"3":[1,2,128],"39":[4]}
Now sum the arrays, and put it back to the structure it originally was.
foreach($tmp as $k => $v){
$new[] = [$k, array_sum($v)];
}
# Output: [[3,131],[39,4]]
But many roads lead to Rome.
Try this code. It may help you.
$array = array(["0" => 3, "1" => 1] , ["0" => 3, "1" => 2], ["0" => 3, "1" => 128], ["0" => 39, "1" => 4]);
$finalArray = [];
foreach($array as $a) {
$finalArray[$a[0]][0] = $a[0];
$finalArray[$a[0]][1] = !isset($finalArray[$a[0]][1]) ? $a[1] : $finalArray[$a[0]][1] + $a[1];
}
echo '<pre>';
print_r($finalArray);
exit;
You could do something like this. I have separated into two foreach. Hope it helps.
<?php
$a = [[3,1],[3,2],[3,128],[39,4]];
$result=[];
$temp = [];
foreach($a as $line) {
$temp[$line[0]] += $line[1];
}
foreach($temp as $k => $value) {
$result[]=[$k ,$value];
}
$data =
[
[3,1],
[3,2],
[3,128],
[39,4]
];
foreach($data as $item)
$sums[$item[0]] = ($sums[$item[0]] ?? 0) + $item[1];
$result = array_map(null, array_keys($sums), $sums);
var_export($result);
Output:
array (
0 =>
array (
0 => 3,
1 => 131,
),
1 =>
array (
0 => 39,
1 => 4,
),
)
$arr = [ [ 3, 1],[ 3, 2 ],[ 3, 128], [ 39, 4]];
$sum = [];
foreach($arr as $value) {
$sum[$value[0]][] = $value[1];
}
foreach($sum as $key=>$value ) {
$result[] = [ $key, array_sum($value)];
}
Output:
Array
(
[0] => Array
(
[0] => 3
[1] => 131
)
[1] => Array
(
[0] => 39
[1] => 4
)
)
I have an array of players each with a number of points.
I can easily sort the array in order of the points using a custom usort function.
But when two players have the same amount of points I need to rank them as the same winning position within the list.
E.g.
Nick - 25
Tom - 18
Chris - 18
Dave - 16
James - 8
In this case the data that I require would be
Nick - 1st
Tom - (joint) 2nd
Chris - (joint) 2nd
Dave 3rd
James 4th
So players with equal scores are designated the same ranking position.
What is the best way of calculating these positions?
Thanks!
This will give you what you want with an additional fix: if you have two players in position 2 the next player should be in position 4. If you don't want this additional fix move $count++; into the if statement.
$count = 0;
$position = 0;
$last_score = -1;
foreach ($players as $player)
{
$count++;
if ($last_score !== $player->score)
{
$position = $count;
}
$player->position = $position;
$last_score = $player->score;
}
I think the following code would do the job as required:
$scores = array('Nick'=>25,'Tom'=>18,'Chris'=>18,'Dave'=>16, 'James'=> 8,);
$scores_numbers = array_unique(array_values($scores));
$scores_counter = array_count_values($scores);
$pos = 1;
foreach($scores_numbers as $num) {
foreach($scores as $name=>$score) {
if($num == $score) {
if($scores_counter[$score] > 1) {
echo "$name - (joint) $pos<br />";
} else {
echo "$name - $pos<br />";
}
}
}
$pos++;
}
I have updated the code to avoid the duplicating output.
If you are retrieving player stats from DB then below code can be useful to rank them :
<?php
$players = [
['name' => 'Ash',
'point' => 0
],
['name' => 'Bob',
'point' => 10
],
['name' => 'Cane',
'point' => 0
],
['name' => 'Dory',
'point' => 6
],
['name' => 'Efat',
'point' => 6
],
];
usort($players, function($v1, $v2){
return $v2['point'] - $v1['point'];
});
$ranking = [];
$currentPosition = 0;
$heighestPoint = PHP_INT_MIN;
foreach($players as $player){
if($heighestPoint !== $player['point']){
$currentPosition++;
$heighestPoint = $player['point'];
}
$ranking[$currentPosition][] = $player;
}
print_r($ranking);
Output :
Array
(
[1] => Array
(
[0] => Array
(
[name] => Bob
[point] => 10
)
)
[2] => Array
(
[0] => Array
(
[name] => Dory
[point] => 6
)
[1] => Array
(
[name] => Efat
[point] => 6
)
)
[3] => Array
(
[0] => Array
(
[name] => Ash
[point] => 0
)
[1] => Array
(
[name] => Cane
[point] => 0
)
)
)
May it helps
/*Below array must be sorted */
$a1=array("Nick"=>25,"Tom"=>18,"Chris"=>18,"Dave"=>16,"James"=>8);
$makeUnique=array_unique($a1);
$makeUnique=array_values($makeUnique);
$pArr=array_map('setPosition',$a1);
print_r($pArr);
function setPosition($a){
Global $makeUnique;
return array_search($a,$makeUnique)+1;
}
OUT PUT
Array ( [Nick] => 1 [Tom] => 2 [Chris] => 2 [Dave] => 3 [James] => 4 )
I used usort to sort assoc array
$players = [["name" => "Nick" , "score" => 25] , ["name" => "Tom" , "score" => 18] , ["name" => "chris" , "score" => 18] , ["name" => "dave" , "score" => 16 ] , ["name" => "james" , "score" => 8]];
usort($players , function($a , $b) {return $b["score"] - $a["score"];} );
var_dump($players);
$lastScore = null;
$pos = 1;
foreach($players as $player)
{
if($lastScore != null && $lastScore == $player["score"])
echo $pos-1 . " - " . $player["name"] . '<br/>';
else
echo $pos++ . " - " . $player["name"] . '<br/>';
$lastScore = $player["score"];
}
checkout this code in teh playground
Below is an example of a function that adds a constant number to the keys of an array -
function addConstantToArrayKeys($seed_array, $constant)
{
foreach($seed_array as $key => $value){
$a[$key + $constant] = $value;
}
return $a;
}
$basearray = [1 => 17, 2 => 24, 3 => 12];
$test = addConstantToArrayKeys($basearray, 19);
The result of this example is:
Array
(
[1] => 17
[2] => 24
[3] => 12
)
Array
(
[20] => 17
[21] => 24
[22] => 12
)
It works as desired but can this method be rewritten somehow using a functional programming approach that can achieve the same result?
I have tried this:
function addConstantToArrayKeys($seed_array, $constant)
{
return array_map(function($key, $element) use($constant)
{return $a[$key + $constant] = $element;},
array_keys($seed_array), array_values($seed_array));
}
But it does not handle the keys as desired. Here is the output -
Array
(
[1] => 17
[2] => 24
[3] => 12
)
Array
(
[0] => 17
[1] => 24
[2] => 12
)
Edit -
Thanks to Progrock's answer, this worked -
function addConstantToArrayKeys($seed_array, $constant)
{
return array_combine(array_map(
function($key) use($constant) {
return $key + $constant;
}, array_keys($seed_array)), $seed_array);
}
May be its too late but this should work for you as you wanted the functional approach.
function addConstantToArrayKeys($basearray, $constant){
$arrayReindexed = [];
array_walk($basearray,function($v,$k) use (&$arrayReindexed, $constant) {
$key = $k;
$k = $key + $constant;
$arrayReindexed[$k] = $v;
});
return $arrayReindexed;
}
$basearray = [1 => 17, 2 => 24, 3 => 12];
$test = addConstantToArrayKeys($basearray, 19);
print '<pre>';
print_r($test);
print '</pre>';
Output:
Array (
[20] => 17
[21] => 24
[22] => 12
)
You could use something unreadable like this. It does not mutate existing array keys.
<?php
$nums = [
1 => 17,
2 => 24,
3 => 12
];
$out = array_combine(array_map(
function($int) {
return $int + 10;
}, array_keys($nums)), $nums);
var_export($out);
Output:
array (
11 => 17,
12 => 24,
13 => 12,
)
Your first example is perfectly functional and readable, but for the naming.
<?php
$nums = [
1 => 17,
2 => 24,
3 => 12
];
$add_num_to_keys = function (array $in, $num) {
$out = [];
foreach($in as $k => $v)
$out[$k + $num] = $v;
return $out;
};
$out = $add_num_to_keys($nums, 10);
var_export($out);
Output:
array (
11 => 17,
12 => 24,
13 => 12,
)
You can't do:
foreach($in as &$k => $v)
$k += 10;
As the key element can't be a reference.
I want a user defined function for sorting a multi dimension array:
<?php
$arr1 = array(
49,
8,
array(
'Muazam',
'Ali',
'Rana',
'Amina',
'Surya',
'Danish',
'Raina',
4,
3,
2,
1,
) ,
7,
6,
5,
4,
3,
2,
1,
0,
);
function abc($arr)
{
$len = count($arr) - 2;
foreach($arr as $key => $value)
{
for ($a = 0; $a <= $len; $a++)
{
if ($arr[$a] > $arr[$a + 1])
{
$temp4 = $arr[$a];
$arr[$a] = $arr[$a + 1];
$arr[$a + 1] = $temp4;
}
}
if (is_array($value))
{
abc($value, $a = $a + 1);
}
}
} //2nd foreach close
echo "<pre>";
print_r($arr);
echo "</pre>";
}
This is a basic usage of a recursive function:
$arr1 = array(49, 8, array(
'Muazam', 'Ali', 'Rana', 'Amina', 'Surya', 'Danish', 'Raina', 4, 3, 2, 1,
), 7, 6, 5, 4, 3, 2, 1, 0);
function recursiveSort(&$array)
{
foreach ($array as &$value) {
if (is_array($value)) {
recursiveSort($value);
}
}
return sort($array);
}
recursiveSort($arr1);
echo '<pre>';
print_r($arr1);
echo '</pre>';
The result would be:
Array
(
[0] => 0
[1] => 1
[2] => 2
[3] => 3
[4] => 4
[5] => 5
[6] => 6
[7] => 7
[8] => 8
[9] => 49
[10] => Array
(
[0] => Ali
[1] => Amina
[2] => Danish
[3] => Muazam
[4] => Raina
[5] => Rana
[6] => Surya
[7] => 1
[8] => 2
[9] => 3
[10] => 4
)
)
Here Is Answer.. Sorting a multi dimensional array without using built in function.
$arr1 = array(1,3,5,'2',array(99,55,array(111,444,array('a','r','p','e','t'),777),66,99),8,9,0,3,1);
function abc(&$arr)
{
$len=count($arr)-2;
foreach($arr as $key => &$value)
{
for ($a=0;$a<=$len;$a++){
if($arr[$a]>$arr[$a+1])
{
$temp4=$arr[$a];
$arr[$a]=$arr[$a+1];
$arr[$a+1]=$temp4;
}
}
if(is_array($value))
{
abc($value,$a=$a+1);
}
}//foreach close
//}//2nd foreach close
echo "<pre>";
return $arr;
echo "</pre>";
}//function close
print_r (abc($arr1));