How to sum multi-dimensional arrays based on some conditions? - php

$arr = [ [
'5'=>[
'BG' => 50,
'CH' => 60,
'LG' => 50,
'MT' => 40,
'MO' => 80,
'PH' => 60,
'GE' =>null
]
], [
'6'=>[
'BG' => 90,
'CH' => 60,
'LG' => 60,
'MT' => 50,
'MO' =>null,
'PH' => 50,
'GE' =>null
]
],[
'7'=>[
'BG' => 80,
'CH' => 55,
'LG' => 65,
'MT' => 50,
'MO' =>null,
'PH' => 50,
'GE' => 55
]
]
];
For each id no 5, 6 and 7 I want to sum up the score. CH, PH, MO and LG will always be compulsory to sum up. But after summing up the compulsory items, I want to sum up the other item based on the following condition.
If MO is null, take the best two from BG, MT and GE. If MO is not null or greater than or equal to 0, I want to take the best one from BG, MT or GE.
So the sum up result will look like below:
Array
(
[5] => Array
(
[score] => 300
)
[6] => Array
(
[score] => 310
)
[7] => Array
(
[score] => 305
)
)
I have tried foreach, but I could not solve the problem. How do I solve this problem?

Here is more core way to achieve this, please find inline doc for explanation,
$keys = array_flip(['BG', 'MT', 'GE']); // best of how many keys
$Ckeys = array_flip(['CH', 'PH', 'MO', 'LG']); // compulsory keys
foreach ($arr as $key => $value) {
// use to pass parameters to reduce function during call
$temp[key($value)] = array_reduce($value, function (&$result, $a) use ($keys, $Ckeys) {
// if mo empty then best of two else best of one
$bestHowMany = (!empty($a['MO']) ? 1 : 2);
// fetching best of keys from $keys
$t = array_intersect_key($a, $keys);
// reverse sort and maintains keys
arsort($t);
// fetch top $bestHowMany Values
$largest2 = array_slice($t, 0, $bestHowMany);
// fetch compulsory values from CKeys
$t1 = array_intersect_key($a, $Ckeys);
// sum by merging compulsory and best of $bestHowMany values
return array_sum(array_merge($t1, $largest2));
});
}
working demo.
Output
Array
(
[5] => 300
[6] => 310
[7] => 305
)

Here, we can first add all our three arrays, then subtract based on the conditions, and our codes would look like,
$arr = [[
'5' => [
'BG' => 50,
'CH' => 60,
'LG' => 50,
'MT' => 40,
'MO' => 80,
'PH' => 60,
'GE' => null,
],
], [
'6' => [
'BG' => 90,
'CH' => 60,
'LG' => 60,
'MT' => 50,
'MO' => null,
'PH' => 50,
'GE' => null,
],
], [
'7' => [
'BG' => 80,
'CH' => 55,
'LG' => 65,
'MT' => 50,
'MO' => null,
'PH' => 50,
'GE' => 55,
],
],
];
$sum_arr = array();
foreach ($arr as $key => $arr2) {
foreach ($arr2 as $key2 => $value) {
$sum_arr[$key2]["score"] = array_sum(array_values($value));
$temp = [$value["BG"], $value["MT"], $value["GE"]];
arsort($temp);
if ($value["MO"] === null) {
$sum_arr[$key2]["score"] -= $temp[2];
} elseif ($value["MO"] != null && $value["MO"] >= 0) {
$sum_arr[$key2]["score"] -= $temp[2] + $temp[1];
} else {
continue;
}
}
}
var_dump($sum_arr);
Either there is a bug in my code, which is most likely, or I did not understand the if conditions right, or less likely the desired output might be incorrect. However, it should not be difficult to debug it.
Output
array(3) {
[5]=>
array(1) {
["score"]=>
int(300)
}
[6]=>
array(1) {
["score"]=>
int(310)
}
[7]=>
array(1) {
["score"]=>
int(300)
}
}

Related

having trouble in transforming a array in php

i have this array
[
[[222] => 1 [333] => 2 [444] => 0],
[[222] => 0 [333] => 2 [444] => 1],
[[222] => 1 [333] => 2 [444] => 0]
]
where [222], [333], [444] are student ids
and 0 means absent
1 means Present
2 means Leave
i want the output will
[ 'student_id' => '222'
'present' => 2 /* total present*/
'absent' => 1 /* total absent*/
'leave' => 0 /* total leave*/
],
[ 'student_id' => '333'
'present' => 0 /* total present*/
'absent' => 0 /* total absent*/
'leave' => 3 /* total leave*/
],
etc.
please give me some soluation in php code
This does exactly what you want, but this site is not a coding service, so i really think you should take the time to understand how i did, and next time try something and share it on your post:
$array = [
[
"222" => 1,
"333" => 2,
"444" => 0
],
[
"222" => 0,
"333" => 2,
"444" => 1
],
[
"222" => 1,
"333" => 2,
"444" => 0
]
];
$results = [];
foreach($array as $k=>$v){
foreach($v as $id=>$value){
if(!isset($results[$id])){
$results[$id] = [
'student_id' => $id,
'present' => 0,
'absent' => 0,
'leave' => 0
];
}
if($value == 0){
$results[$id]['absent']++;
}
if($value == 1){
$results[$id]['present']++;
}
if($value == 2){
$results[$id]['leave']++;
}
}
}
$results = array_values($results);
print_r($results);
This looks like JSON value with there respective keys. You may do that firstly you can arrange these values in PHP ARRAY using foreach then convert that array in JSON.
foreach looping is the best way to access each key/value pair from an array.
foreach($featured as $key => $value){...}
The $key => $value in the foreach loop refers to the key-value pairs in associative arrays, where the key serves as the index to determine the value instead of a number like 0,1,2,... In PHP, associative arrays look like this
$featured = array('student_id' => '111', 'present' => '2', etc.);

How can I search an array for specific values?

I need some help with how I can search an array from a search box.
Lets say I search for the $ticker and write BTC
It will then print out:
The last known currency for BTC is 57
I only want it to print out $k3 values.
Appreciate if you could take your time and guide me in the right direction :)
<form method="POST" action="">
<input type="text" name="Searcharray" name="searcharray">
<input type="submit" value="Search" name="searcharray">
</form>
<?php
$ticker = array(
0 => "BTC",
1 => "ETH",
2 => "LTC",
3 => "XMR",
4 => "XRP"
);
$name = array(
0 => "Bitcoin",
1 => "Ethereum",
2 => "Litecoin",
3 => "Monero",
4 => "Ripple"
);
$k1 = array(
0 => 1,
1 => 2,
2 => 3,
3 => 4,
4 => 5
);
$k2 = array(
0 => 11,
1 => 12,
2 => 13,
3 => 14,
4 => 15
);
$k3 = array(
0 => 17,
1 => 27,
2 => 37,
3 => 47,
4 => 57
);
?>
array_search would help - http://php.net/manual/de/function.array-search.php
$index = array_search('BTC', $ticker);
$value = $k3[$index];
Why dont you make such a structure?:
$data = [
'BTC' => [
'name' => 'Bitcoin',
'k1' => 1,
'k2' => 11,
'k3' => 17
], ...
];
then it would be:
$value = $data['BTC']['k3'];
$index = array_search("BTC", $ticker);
if ($index !== FALSE) {
$currency = $k3[$index];
echo "The last known currency of BTC is $currency";
}
But things would be easier if you used a 2-dimensional associative array:
$data = [
"BTC" => ["name" => "Bitcoin", "k1" => 1, "k2" => 11, "k3" => 17],
"ETH" => ["name" => "Ethereum", "k1" => 2, "k2" => 12, "k3" => 27],
...
];
Then you can do:
if (isset($data["BTC"])) {
$currency = $data["BTC"]["k3"];
echo "The last known currency of BTC is $currency";
}

Is there a simple way to manipulate bitwise enum in PHP?

I'm creating a custom user profile for a game (osu!) and I'm trying to get which "mods" has been used in a "top play".
The API provides a decimal number containing each mods the player used in his play.
Ex: 72 for DoubleTime+Hidden mods, since DoubleTime is 64 and Hidden 8
$hidden = 8;
$doubletime = 64;
$hiddendoubletime = ($hidden|$doubletime);
I want to, from 72 for example, know that its 8 and 64.
or even from 88 that it's 8 and 16 and 64.
I was thinking about transform 88 for example in binary (01011000), then detect all "1" positions since each "1" gives a mod.
Here : 01011000 -
the first "1" at position 4 is the Hidden mod, the second "1" a position 5 is the Hardrock mod and finally, the "1" at position 7 is the DoubleTime mod.
Then enum is the following :
enum Mods
{
None = 0,
NoFail = 1,
Easy = 2,
TouchDevice = 4,
Hidden = 8,
HardRock = 16,
SuddenDeath = 32,
DoubleTime = 64,
Relax = 128,
HalfTime = 256,
Nightcore = 512, // Only set along with DoubleTime. i.e: NC only gives 576
Flashlight = 1024,
Autoplay = 2048,
SpunOut = 4096,
Relax2 = 8192, // Autopilot
Perfect = 16384, // Only set along with SuddenDeath. i.e: PF only gives 16416
Key4 = 32768,
Key5 = 65536,
Key6 = 131072,
Key7 = 262144,
Key8 = 524288,
FadeIn = 1048576,
Random = 2097152,
Cinema = 4194304,
Target = 8388608,
Key9 = 16777216,
KeyCoop = 33554432,
Key1 = 67108864,
Key3 = 134217728,
Key2 = 268435456,
ScoreV2 = 536870912,
LastMod = 1073741824,
}
As you can see, the list is pretty big, so I can't just try each mods combinations in if() condition.
I would do something like this....
<?php
$user_options = 88;
$no_options = array ( 'None' => 0 );
$game_options = array (
'NoFail' => 1,
'Easy' => 2,
'TouchDevice'=> 4,
'Hidden' => 8,
'HardRock' => 16,
'SuddenDeath' => 32,
'DoubleTime' => 64,
'Relax' => 128,
'HalfTime' => 256,
'Nightcore' => 512,
'Flashlight' => 1024,
'Autoplay' => 2048,
'SpunOut' => 4096,
'Relax2' => 8192,
'Perfect' => 16384,
'Key4' => 32768,
'Key5' => 65536,
'Key6' => 131072,
'Key7' => 262144,
'Key8' => 524288,
'FadeIn' => 1048576,
'Random' => 2097152,
'Cinema' => 4194304,
'Target' => 8388608,
'Key9' => 16777216,
'KeyCoop' => 33554432,
'Key1' => 67108864,
'Key3' => 134217728,
'Key2' => 268435456,
'ScoreV2' => 536870912,
'LastMod' => 1073741824
);
$filtered = array_filter ( $game_options, function ( $value ) use ( $user_options )
{
return ( $value & $user_options ) == $value ? $value : NULL;
});
if ( empty ( $filtered ) )
{
print_r ( $no_options );
}
else
{
print_r ( $filtered );
}
?>
I was thinking, it would be best to only cycle through the user(s) set options, that way you don't have to cycle through all the game_options when maybe only a few lower numbered bits are set...
<?php
$user_options = 344;
$game_options = array (
'NoFail' => 1,
'Easy' => 2,
'TouchDevice'=> 4,
'Hidden' => 8,
'HardRock' => 16,
'SuddenDeath' => 32,
'DoubleTime' => 64,
'Relax' => 128,
'HalfTime' => 256,
'Nightcore' => 512,
'Flashlight' => 1024,
'Autoplay' => 2048,
'SpunOut' => 4096,
'Relax2' => 8192,
'Perfect' => 16384,
'Key4' => 32768,
'Key5' => 65536,
'Key6' => 131072,
'Key7' => 262144,
'Key8' => 524288,
'FadeIn' => 1048576,
'Random' => 2097152,
'Cinema' => 4194304,
'Target' => 8388608,
'Key9' => 16777216,
'KeyCoop' => 33554432,
'Key1' => 67108864,
'Key3' => 134217728,
'Key2' => 268435456,
'ScoreV2' => 536870912,
'LastMod' => 1073741824
);
function get_options ( $game_options, $user_options )
{
/* if no options are set, return this */
$nil = array ( 'None' => 0 );
/* if option(s) are set, return the array of set option(s) */
$set = array ( );
/* only loop the $game_options up until the max set $user_options */
$stop = $user_options;
foreach ( $game_options AS $on => $ov )
{
if ( $ov > $stop )
{
break;
}
else if ( ( $ov & $user_options ) == $ov )
{
$set[$on] = $ov;
$stop -= $ov;
}
}
return empty ( $set ) ? $nil : $set;
}
print_r ( get_options ( $game_options, $user_options ) );
?>

how to calculate the sum of same array values in PHP

I have an array like this
$estimate[0]=>
'gear' =>'MMG'
'total' => 315
'efforts' => 9
'afh' => 18
$estimate[1]=>
'gear' =>'MMG'
'total' => 400
'efforts' => 2
'afh' => 6
$estimate[2]=>
'gear' =>'BOO'
'total' => 200
'efforts' => 20
'afh' => 16
$estimate[3]=>
'gear' =>'BOB'
'total' => 250
'efforts' => 20
'afh' => 16
I want to calculate the sum of total, efforts and afh in which gear is same and it will be stored in the another array. Following my coding is working when the array (estimate) size is less than 5.
$calculate = array();
for($et=0;$et<count($estimate);):
if($et==0):
$calculate[$et]['gear'] = $estimate[$et]['gear'];
$calculate[$et]['total'] = $estimate[$et]['total'];
$calculate[$et]['efforts'] = $estimate[$et]['efforts'];
$calculate[$et]['afh'] = $estimate[$et]['afh'];
goto loopend;
endif;
for($cet=0;$cet<count($calculate);$cet++):
if($estimate[$et]['gear'] == $calculate[$cet]['gear']):
$calculate[$cet]['total'] = $calculate[$cet]['total'] + $estimate[$et]['total'];
$calculate[$cet]['efforts'] = $calculate[$cet]['efforts'] + $estimate[$et]['efforts'];
$calculate[$cet]['afh'] = $calculate[$cet]['afh'] + $estimate[$et]['afh'];
goto loopend;
endif;
endfor;
$calculate[$et]['gear'] = $estimate[$et]['gear'];
$calculate[$et]['total'] = $estimate[$et]['total'];
$calculate[$et]['efforts'] = $estimate[$et]['efforts'];
$calculate[$et]['afh'] = $estimate[$et]['afh'];
goto loopend;
loopend:$et++;
endfor;
The coding is not working more than many gears. Sometimes it works. I can't find the issues. Please help me to solve the issues.
You might use array_reduce:
$result = array_reduce($estimate, function($carry, $item) {
if (!isset($carry[$item["gear"]])) {
$carry[$item["gear"]] = $item;
return $carry;
}
$carry[$item["gear"]]["total"] += $item["total"];
$carry[$item["gear"]]["efforts"] += $item["efforts"];
$carry[$item["gear"]]["afh"] += $item["afh"];
return $carry;
});
Demo
As per my comment use foreach loop when your array length is not define
Here is your desired code
<?php
$estimate = array(
"0" => array (
"gear" => 35,
"total" => 30,
"efforts" => 39,
"afh" => 39,
),
"1" => array (
"gear" => 35,
"total" => 30,
"efforts" => 39,
"afh" => 39,
),
"2" => array (
"gear" => 35,
"total" => 30,
"efforts" => 39,
"afh" => 39,
),
);
$gear=0;
$total=0;
$efforts=0;
$afh=0;
foreach ($estimate as $key => $value) {
$gear=$gear+$value['gear'];
$total=$gear+$value['total'];
$efforts=$gear+$value['efforts'];
$afh=$gear+$value['afh'];
}
echo "<pre>";
$result = array('gear' => $gear, 'total' => $total,'efforts' => $efforts,'afh' => $afh);
echo "<pre>";
print_r($result);
you can check the result HERE
<?php
$new_arr = array();
$estimate[0] =array(
'gear' =>'MMG',
'total' => 315,
'efforts' => 9,
'afh' => 18
);
$estimate[1]=array(
'gear' =>'MMG',
'total' => 400,
'efforts' => 2,
'afh' => 6,
);
$estimate[2]=array(
'gear' =>'BOO',
'total' => 200,
'efforts' => 20,
'afh' => 16,
);
$estimate[3]=array(
'gear' =>'BOB',
'total' => 250,
'efforts' => 20,
'afh' => 16,
);
foreach ($estimate as $key => $value) {
$new_arr[$value['gear']] = array(
'total' => (isset($new_arr[$value['gear']]['total']) ? ($new_arr[$value['gear']]['total'] + $value['total']) : $value['total'] ),
'efforts' => (isset($new_arr[$value['gear']]['efforts']) ? ($new_arr[$value['gear']]['efforts'] + $value['efforts']) : $value['efforts'] ),
'afh' => (isset($new_arr[$value['gear']]['afh']) ? ($new_arr[$value['gear']]['afh'] + $value['afh']) : $value['afh'] )
);
}
echo "<pre>";print_r($new_arr);

PHP array stringify

In a lyrics application I'm coding, I'm using an array to print an artists table. The artists array looks like this:
$artists = [
[ "Avril Lavigne" ],
[ "3 Doors Down" ],
[ "Celine Dion" ],
[ "Evanescence" ],
[ "Shania Twain" ],
[ "Green Day" ],
//...
];
Before printing it, I do some modification to the array. I have a folder for each artist that contains the lyrics files. I add the folder names to the $artists array for later use:
$folder_fix = [
[" ", "_" ],
[".", "" ],
["&", "n" ],
];
for ($i = 0; $i < count($artists); $i++) {
$folder_name = strtolower($artists[$i][0]);
for ($k = 0; $k < count($folder_fix); $k++) {
$folder_name = str_replace($folder_fix[$k][0], $folder_fix[$k][1], $folder_name);
}
array_push($artists[$i], $folder_name);
}
Later, I add the album and track count for each artist to the array:
$lyrics_base = "lyrics/";
for ($i = 0; $i < count($artists); $i++) {
$albums_path = $lyrics_base . $artists[$i][1] . "/*";
$tracks_path = $lyrics_base . $artists[$i][1] . "/*/*";
$albums = count(glob($albums_path));
$tracks = count(glob($tracks_path));
array_push($artists[$i], $albums);
array_push($artists[$i], $tracks);
}
The end result of the array looks like this:
$artists = [
[ "Avril Lavigne", "avril_lavigne", 5, 61 ],
[ "3 Doors Down", "3_doors_down", 5, 13 ],
[ "Celine Dion", "celine_dion", 7, 22 ],
[ "Evanescence", "evanescence", 4, 10 ],
[ "Shania Twain", "shania_twain", 3, 12 ],
[ "Green Day", "green_day", 8, 26 ],
//...
];
Now, my problem is that this process happens every time I visit the page. The 2nd, 3rd, and the 4th columns are created again and again. I think this is redundant.
I want to save the end result of the array and use it on the page. If this was JavaScript I'd use JSON.stringify(), but in PHP I don't know how to get the end result of the array. print_r() doesn't do the job, because it prints it like this:
Array
(
[0] => Array
(
[0] => Avril Lavigne
[1] => avril_lavigne
[2] => 5
[3] => 61
)
[1] => Array
(
[0] => 3 Doors Down
[1] => 3_doors_down
[2] => 5
[3] => 13
)
...
I want it like this:
[
[
"Avril Lavigne",
"avril_lavigne",
5,
61
],
[
"3 Doors Down",
"3_doors_down",
5,
13
],
//...
]
Is there a way to print the array the JSON.stringify() way?
Is this what you want?
echo json_encode($artists)
PHP: json_encode
You can use this simple function from my CMS EFFCORE:
function data_stringify($data) {
switch (gettype($data)) {
case 'string' : return '\''.addcslashes($data, "'\\").'\'';
case 'boolean': return $data ? 'true' : 'false';
case 'NULL' : return 'null';
case 'object' :
case 'array' :
$expressions = [];
foreach ($data as $c_key => $c_value) {
$expressions[] = data_stringify($c_key).' => '.
data_stringify($c_value);
}
return gettype($data) === 'object' ?
'(object)['.implode(', ', $expressions).']' :
'['.implode(', ', $expressions).']';
default: return (string)$data;
}
}
TEST
var_dump( data_stringify(-1 ) === '-1' );
var_dump( data_stringify(-1.1 ) === '-1.1' );
var_dump( data_stringify(123e1 ) === '1230' ); # exponential notation
var_dump( data_stringify(0x123 ) === '291' ); # hexadecimal notation
var_dump( data_stringify(01234 ) === '668' ); # octal notation
var_dump( data_stringify(0b101 ) === '5' ); # binary notation
var_dump( data_stringify('а123') === "'а123'" );
var_dump( data_stringify('123а') === "'123а'" );
var_dump( data_stringify(true ) === 'true' );
var_dump( data_stringify(false ) === 'false' );
var_dump( data_stringify(null ) === 'null' );
array
var_dump(
data_stringify([
100,
'200',
'item3' => 300,
'item4' => '400',
'item5' => 'value500'
]) === "[".
"0 => 100, ".
"1 => '200', ".
"'item3' => 300, ".
"'item4' => '400', ".
"'item5' => 'value500']"
);
object
var_dump(
data_stringify((object)[
'prop1' => 100,
'prop2' => '200',
'prop3' => 'value300'
]) === "(object)[".
"'prop1' => 100, ".
"'prop2' => '200', ".
"'prop3' => 'value300']"
);
array with object
var_dump(
data_stringify([
100,
'200',
'item3' => (object)['prop1' => 1, 'prop2' => '2', 'prop3' => 'value3'],
'item4' => '400',
'item5' => 'value500'
]) === "[".
"0 => 100, ".
"1 => '200', ".
"'item3' => (object)['prop1' => 1, 'prop2' => '2', 'prop3' => 'value3'], ".
"'item4' => '400', ".
"'item5' => 'value500']"
);
object with array
var_dump(
data_stringify((object)[
'prop1' => 1,
'prop2' => '2',
'prop3' => [100, '200', 'item3' => '300', 'item4' => 'value400'],
'prop4' => 'value4'
]) === "(object)[".
"'prop1' => 1, ".
"'prop2' => '2', ".
"'prop3' => [0 => 100, 1 => '200', 'item3' => '300', 'item4' => 'value400'], ".
"'prop4' => 'value4']"
);
The print_r have second parameter.
$string=print_r($array, true);

Categories