I'm trying to combine the scores of employee for my program. My sample is one employee is evaluated more than one. So basically, if employee 1 have scored of 87 and 90 the total should be 177. After computation, I need to return the result with the highest score.
Here so far my sample code (I simplified my code for this question because it is too long to post the original code):
$scores = array(
array(1, "allan", 90),
array(2, "allan", 85),
array(3, "mark", 100),
array(4, "jason", 88),
array(5, "allan", 92),
array(6, "mark", 77),
array(7, "mark", 88),
array(8, "jason", 90)
);
print_r($scores);
get_topemployee($scores);
function get_topemployee($scores) {
$total_score = 0;
$combined_score = array();
foreach($scores as $key) {
for($i=0; count($scores) <= $i; $i++) {
if($key[0] == $key[0][$i]) {
$total_score += $key[1];
}
$combined_score[] = array($key[0], $key[1], $total_score);
}
}
$employee = ""; // employee with highest score
$compare_score = 0;
foreach($combined_score as $value) {
$compare_score = $value[1];
if($value[1] >= $compare_score) {
$employee = $value[0];
}
}
return $employee;
}
The result does not return the employee with highest score and not sure which in my code is incorrect. thanks for help
do this:- https://3v4l.org/WhVaN
You can use array_reduce to convert your scores array into an array of total scores indexed by employee:
$scores = array_reduce($scores, function ($c, $v) {
$name = $v[1];
if (isset($c[$name])) {
$c[$name] += $v[2];
}
else {
$c[$name] = $v[2];
}
return $c;
}, array());
You can then use arsort to sort the array in reverse order while maintaining the key association. You can then use key to get the key of the first element, which will be the name of the employee with the highest score:
arsort($scores);
echo key($scores);
Output:
allan
Demo on 3v4l.org
To print out all the scores, you can simply print_r($scores):
Array (
[allan] => 267
[mark] => 265
[jason] => 178
)
Alternatively to print just the highest score, change echo key($scores); to echo key($scores) . ' ' . current($scores);:
allan 267
Updated demo.
You can do that with simple foreach loop:
foreach($scores as $e) {
if (!isset($res[$e[1]])) $res[$e[1]] = 0;
$res[$e[1]] += $e[2];
}
print_r(array_keys($res, max($res)));
Live example: 3v4l
Here is a snippet for you, please see inline doc for explanation
$result = [];
array_walk($scores, function($item) use(&$result){
// pushing on the behalf of name and checking if not isset with '??'
$result[$item[1]] = ($result[$item[1]] ?? 0) + $item[2];
});
// searching for index with max value in result and show max value too
echo array_search(max($result), $result).' -> '. max($result);
array_search — Searches the array for a given value and returns the first corresponding key if successful
array_walk — Apply a user supplied function to every member of an array
Output
allan -> 267
Demo Link.
$scores = [
[1, 'allan', 90],
[2, 'allan', 85],
[3, 'mark', 100],
[4, 'jason', 88],
[5, 'allan', 92],
[6, 'mark', 77],
[7, 'mark', 88],
[8, 'jason', 90]
];
function maxScore(array $scores): string {
$preparedScores = [];
foreach ($scores as $score) {
$key = $score[1];
$value = $score[2];
if (isset($preparedScores[$key])) {
$preparedScores[$key] += $value;
} else {
$preparedScores[$key] = $value;
}
}
arsort($preparedScores);
return array_key_first($preparedScores);
}
echo maxScore($scores);
Result:
allan
$scores = array(
array(1, "allan", 90),
array(2, "allan", 85),
array(3, "mark", 100),
array(4, "jason", 88),
array(5, "allan", 92),
array(6, "mark", 77),
array(7, "mark", 88),
array(8, "jason", 90)
);
get_topemployee($scores);
function get_topemployee($scores) {
$total_score = 0;
$combined_score = array();
$highest_score = 0;
$highest_employee = '';
foreach($scores as $key => $value) {
if ( ! isset($combined_score[$value[1]])) {
$combined_score[$value[1]] = $value[2];
}
else {
$combined_score[$value[1]] += $value[2];
}
if ($highest_score < $combined_score[$value[1]]) {
$highest_score = $combined_score[$value[1]];
$highest_employee = $value[1]; //the highest value employee
}
}
return $highest_employee;
}
Related
I need to add an item every 6th position.
So it would look like this:
[
//item1
//item2
//item3
//item4
//item5
//NEW ITEM HERE
//item7
//item8
//item9
//item10
//item11
//NEW ITEM
]
I already tried this:
foreach($ports as $key => $port)
{
if($key %9 == 2) {
$ports->splice($key, 0, [$ads]);
}
}
But that's not working any idea?
Use array_chunk and add element to each of sub-arrays:
$portsChunks = array_chunk($ports, 5); // Split array to sub-arrays of max-5 elements.
// Add new element if chunk is full length.
// Means last one will not receive new element if it's shorter than 5
array_walk($portsChunks, function (&$array) {
if (count($array) == 5) {
$array[] = 'New Item';
}
});
// Use arguments unpacking to pass all chunks to array_merge
$ports = array_merge(...$portsChunk);
Example
You can use foreach loop:
$ports = range(1,50);
$new_ports = [];
foreach ($ports as $key => $port) {
$new_ports[] = $port;
if(!(($key+1)%5))
$new_ports[] = 'New item';
}
print_r($new_ports);
$ports = [1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6];
$ports = array_chunk($ports, 5);
foreach ($ports as &$port){
array_push($port, 'new value');
}
unset($port);
if(count($ports[count($ports)-1]) < 6){
array_pop($ports[count($ports)-1]);
}
$ports = array_merge(...$ports);
you just need a new array to hold all of your data. and then you iterate over your old array and after each 5th position insert a new element. something like this
$result = [];
$ports = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
$porstCount = count($ports);
for ($i = 0; $i < $portsCount; $i++) {
$result[] = $ports[$i];
if ($i > 0 && $i % 5 === 0) {
$result[] = 'new element';
}
}
// $result will be [1, 2, 3, 4, 5, 'new element', 6, 7, 8, 9, 10, 'new element', 11, 12]
I hope below case solves your problem:
$newarr = array();
$cnt = 1;
foreach($arr as $key=>$value){
$newarr[] = $value;
if($cnt%5 == 0){
$newarr[] = 'this is new item';
}
$cnt++;
}
print_r($newarr);
For example, in php
$arr = [9, 4, 3, 5, 2, 6];
then,
$output = [[0,0], [1,2], [2,2], [1,1], [4,1], [1,0]];
[0, 0] = the bigger elements of 9 is 0 on both side
[1, 2] = the bigger elements of 4 is 1 (9) on left and 2 (5, 6) on right side ... [ 9 > 4] - [ 5 > 4, 6 > 4 ]
[2, 2] = the bigger elements of 3 is 2 (9, 4) on the left and 2 (5, 6) on right side
[1, 1] = the bigger elements of 5 is 1 (9) on the left and 1 (6) on the right side
[4, 1] = the bigger elements of 2 (9, 4, 3, 5) is 4 on the left and 1 (6) on the right side
[1, 0] = the bigger elements of 6 is 1 (9) on the left and 0 (no elements after 6) on the right side
I want it in O(n log(n)), is it possible?
Looks like lots of answers already, you could do this with some of the array functions like some of the answers did, but since this is probably for your homework best to keep it simple. I keep track of whether it's left or right that should be incremented each iteration by using the $side variable.
$arr = [9, 4, 3, 5, 2, 6];
$results = [];
for ($x = 0; $x < count($arr); $x++) {
$results[$x] = [0,0];
$side = 0;
for ($y = 0; $y < count($arr); $y++) {
if ($arr[$y] > $arr[$x]) {
$results[$x][$side]++;
} elseif ($arr[$x] == $arr[$y]) {
$side = 1;
}
}
}
You need to loop through $arr to get each value, and then, in the loop, loop again through $arr to get the other values. Then, in the second loop, you build your output array by comparing both the value (to know if the number is, indeed, bigger) and the key (to know if it's on the left or the right).
$arr = array(9, 4, 3, 5, 2, 6);
$output = array();
foreach ($arr as $key=>$value) {
$out = array(0, 0);
foreach ($arr as $key2=>$value2) {
if ($key2 == $key) # If it's the same element
continue;
if ($value2 > $value) {
if ($key2 < $key)
$out[0]++;
else
$out[1]++;
}
}
$output[] = $out;
}
print_r($output);
See the output here.
Try this:
function fix_array($array) {
$return_array = array();
foreach ($array as $i => $value){
$left = array_slice($array, 0, $i);
$count_left = count(array_filter($left, function($var) use($value){
return $var > $value;
}));
$right = array_slice($array, $i + 1);
$count_right = count(array_filter($right, function($var) use($value){
return $var > $value;
}));
$return_array[] = [$count_left, $count_right];
}
return $return_array;
}
$arr = [9, 4, 3, 5, 2, 6];
$new_array = fix_array($arr);
print_r($new_array);
Simply compare it with left and right values. Try this:
$arr = [9, 4, 3, 5, 2, 6];
$total = count($arr);
$new_arr=array();
foreach ($arr as $key => $value) {
$left = 0;
$right = 0;
for ($i=0; $i < $total; $i++) {
if($key > $i && $arr[$i] > $arr[$key])
{
$left++;
}
elseif ($key < $i && $arr[$i] > $arr[$key]) {
$right++;
}
}
$new_arr[]=[$left,$right];
}
echo "<pre>";
print_r($new_arr);
Try the following code using array_walk()
<?php
$arr = [9, 4, 3, 5, 2, 6];
$finalArray =[];
array_walk($arr, function($value,$key) use(&$finalArray,&$arr) {
$param ['pre_val']=0;
$param ['post_val']=0;
$param ['current_index'] = $key;
$param ['current_value'] = $value;
$arr2 = $arr;
array_walk($arr2, function(&$value,$key) use(&$finalArray,&$param) {
if($key < $param['current_index']){
if($value > $param['current_value']){$param['pre_val'] ++;}
}else{
if($value > $param['current_value']){$param['post_val'] ++;}
}
$finalArray[$param['current_index']][0] = $param['pre_val'];
$finalArray[$param['current_index']][1] = $param['post_val'];
});
});
print_r($finalArray);
I was just going through these questions for PHP and got stuck at one of them. The question is:
You have a PHP 1 dimensional array. Please write a PHP function that
takes 1 array as its parameter and returns an array. The function must
delete values in the input array that shows up 3 times or more?
For example, if you give the function
array(1, 3, 5, 2, 6, 6, 6, 3, 1, 9)the function will returnarray(1, 3, 5, 2, 3, 1, 9)
I was able to check if they are repeating themselves but I apply it to the array I am getting as input.
function removeDuplicate($array){
$result = array_count_values( $array );
$values = implode(" ", array_values($result));
echo $values . "<br>";
}
$qArray = array(1, 3, 5, 2, 6, 6, 6, 3, 1, 9);
removeDuplicate($qArray);
One more thing, we cannot use array_unique because it includes the value which is repeated and in question we totally remove them from the current array.
Assuming the value may not appear 3+ times anywhere in the array:
$array = array(1, 3, 5, 2, 6, 6, 6, 3, 1, 9);
// create array indexed by the numbers to remove
$remove = array_filter(array_count_values($array), function($value) {
return $value >= 3;
});
// filter the original array
$results = array_values(array_filter($array, function($value) use ($remove) {
return !array_key_exists($value, $remove);
}));
If values may not appear 3+ times consecutively:
$results = [];
for ($i = 0, $n = count($array); $i != $n;) {
$p = $i++;
// find repeated characters
while ($i != $n && $array[$p] === $array[$i]) {
++$i;
}
if ($i - $p < 3) {
// add to results
$results += array_fill(count($results), $i - $p, $array[$p]);
}
}
This should work :
function removeDuplicate($array) {
foreach ($array as $key => $val) {
$new[$val] ++;
if ($new[$val] >= 3)
unset($array[$key]);
}
return $array;
}
run this function i hope this help..
function removeDuplicate($array){
$result = array_count_values( $array );
$dub = array();
$answer = array();
foreach($result as $key => $val) {
if($val >= 3) {
$dub[] = $key;
}
}
foreach($array as $val) {
if(!in_array($val, $dub)) {
$answer[] = $val;
}
}
return $answer;
}
You can use this function with any number of occurrences you want - by default 3
function removeDuplicate($arr, $x = 3){
$new = $rem = array();
foreach($arr as $val) {
$new[$val]++;
if($new[$val]>=$x){
$rem[$val]=$new[$val];
}
}
$new = array_keys(array_diff_key($new, $rem));
return $new;
}
I think it is getting correct output. just try once.
$array=array(1,2,3,7,4,4,3,5,5,6,7);
$count=count($array);
$k=array();
for($i=0;$i<=$count;$i++)
{
if(!in_array($array[$i],$k))
{
$k[]=$array[$i];
}
}
array_pop($k);
print_r($k);
in this first $k is an empty array,after that we are inserting values into $k.
You should use array_unique funciton.
<?php
$q = array(1, 3, 5, 2, 6, 6, 6, 3, 1, 9);
print_r(array_unique($q));
?>
Try it and let me know if it worked.
Suppose I have a multidimensional array
$num1 = array(1, 4, 6, 12, 15, 16, 21, 34, 25, 29);
$num2 = array(1, 5, 18, 19, 23, 19, 23, 45, 23, 16);
$array = array($num1, $num2);
I want to extract all the values from $array where the $array[0] values meet some condition e.g. have a value between 10 & 20.
to get the required values from $array I can use this code:
$count = count($array[0]);
$new_array = array_fill(0, $count, array());
for($i = 0; $i < $count; $i++)
{
if($array[0][$i] >= 10 && $array[0][$i] <= 20)
{
$new_array[0][] = $array[0][$i];
$new_array[1][] = $array[1][$i];
}
}
//I get the array that I need
print_r($new_array);
This is the code I need to change every time
$array[0][$i] >= 10 && $array[0][$i] <= 20 (condition --> values from the first sub array are >= 10 and <= 20)
result would be
Array(0 => Array(0 => 12, 1 => 15, 2 => 16), 1 => Array(0 => 19, 1 => 23, 2 => 19))
another condition
$array[1][$i] >= 20 && $array[1][$i] <= 30 (condition --> values from the second sub array are >= 20 and <= 30)
result would be
Array(0 => Array(0 => 15, 1 => 21, 2 => 25), 1 => Array(0 => 23, 1 => 23, 2 => 23))
I need to do such operations with different columns using different conditions. So, instead of writing code for looping every time, I want to create a function with condition as an argument. Is it possible, if so how?
I would like to have a function with three arguments as shown below
function_name ($array, $column_num, $condition)
Any alternative solutions are also welcome.... :)
Code I used finally to get this done....
<?php
function mdarray_condition_extract($array, $column, $condition)
{
$count = count($array[0]);
$nsac = count($array);
$new_array = array_fill(0, $nsac, array());
for ($i = 0; $i < $count; $i++)
{
$valToTest = $array[$column][$i];
if ($condition($valToTest))
{
for($k = 0; $k < $nsac; $k++)
{
$new_array[$k][] = $array[$k][$i];
}
}
}
return $new_array;
}
$array = array(array(1, 4, 6, 12, 15, 16), array(1, 5, 18, 19, 23, 19));
$columns = array(0,1,0);
$conditions = [
0 => function($val){return $val >= 10 && $val <= 20;},
1 => function($val){return $val >= 20 && $val <= 30;},
2 => function($val){return $val == 6 || $val == 20;}
];
$combo = array($columns, $conditions);
$condcount = count($combo[0]);
for($i = 0; $i < $condcount; $i++)
{
print_r(mdarray_condition_extract($array, $combo[0][$i], $combo[1][$i])); echo "<br><br>";
}
?>
Thanks all for the response, it helped me in a great way...!!
Your existing code is very close.
function filterParallelArrays($array, $predicateFilterIndex, $predicate)
{
$count = count($array[0]);
$new_array = array_fill(0, $count, array());
for ($i = 0; $i < $count; $i++)
{
$valToTest = $array[$predicateFilterIndex][$i];
if ($predicate($valToTest))
{
$new_array[0][] = $array[0][$i];
$new_array[1][] = $array[1][$i];
}
}
return $new_array;
}
$predicate = function($val)
{
return $val >= 10 && $val <= 20;
};
print_r(filterParallelArrays($array, 0, $predicate));
You question is about filtering your arrays. For that, PHP has built-in function array_filter() . It takes callback for filtering values.
If I got your question correctly, you want to apply filter to your sub-arrays - and, probably, with different conditions. Normally, if do that statically, it is:
$array[0] = array_filter($array[0], function($x)
{
return $x>=10 && $x<=20; //item between 10 and 20
});
-but if you have predefined list for each column, you can fill a map:
$conditions = [
//column index => condition callback:
0 => function($x){ return $x>=10 && $x<=20; },
1 => function($x){ return $x==50 || $x==80; },
//e t.c.
];
foreach($array as $key=>$column)
{
if(array_key_exists($key, $conditions))
{
$array[$key] = array_filter($array[$key], $conditions[$key]);
}
}
So, using array_filter() - you can do it natively, I think you won't need your own custom function to do this (because wrapping native function has little sense in this case).
Given your latest update, you could do something like this. But I'm still not really sure what your objective is here, so this might be totally out to lunch.
function array_function($key, $lcond, $rcond)
{
$count = count($array[0]);
$new_array = array_fill(0, $count, array());
for($i = 0; $i < $count; $i++)
{
if($array[$key][$i] >= $lcond && $array[$key][$i] <= $rcond)
{
$new_array[0][] = $array[0][$i];
$new_array[1][] = $array[$key][$i];
}
}
//I get the array that I need
return $new_array;
}
I'm completely new to programming and have been struggling with this for at least a couple of hours. It simply deals 5 cards to a player. This is the code I have:
<?php
//setting up arrays
$cardLocation = array();
$suits = array("Hearts", "Diamonds", "Spades", "Clubs");
$ranks = array("Ace", 2, 3, 4, 5, 6, 7, 8, 9, 10, "Jack","Queen", "King");
//filling the deck
for($rank=0; $rank<13; $rank++){
for($suit=0; $suit<4; $suit++){
$cardLocation[$rank][$suit] = "deck";
}
}
//dealing the cards to a player
for($i=0; $i<5; $i++){
$duplicate = true;
while($duplicate){
$suit = rand(1, 4);
$rank = rand(1, 13);
if($cardLocation[$rank][$suit] == "deck"){
$cardLocation[$rank][$suit] = "player";
$duplicate = false;
}
}
}
?>
I'm trying to figure out a way of storing each value of the for loop into an array and then printing it out. Have had a few ideas but all of them failed. Any help would be welcomed.
I'm not sure that a two dimensional array is a requirement, but if it is not you could consider something like this:
<?php
const NUMBER_OF_CARDS_TO_DRAW = 5;
$cardLocation = array();
$suits = array("Hearts", "Diamonds", "Spades", "Clubs");
$ranks = array("Ace", 2, 3, 4, 5, 6, 7, 8, 9, 10, "Jack","Queen", "King");
//filling the deck
$deck = [];
foreach ($suits as $suit) {
foreach ($ranks as $rank) {
$deck[] = "$suit $rank";
}
}
// http://php.net/manual/en/function.shuffle.php
shuffle($deck);
$playerHand = [];
for ($i=0;$i<NUMBER_OF_CARDS_TO_DRAW;$i++) {
// http://php.net/manual/en/function.array-shift.php
$randomCard = array_shift($deck);
if (is_null($randomCard)) {
// this happens if you try to draw too many cards
break;
}
$playerHand[] = $randomCard;
}
print_r($playerHand);