php: Keep only max values in an array? - php

Given a simple array like
$testarr = array("Donna"=>3, "Luke" => 4, "Pete" =>4, "Lola" => 1);
How can I keep only the max values?
I am aware I could do a
max($testarr);
and then loop through the array removing values that differ, but maybe sg like array_filter, or a more elegant one liner solution is available.

Here is your one-liner using array_filter:
<?php
$testarr = array("Donna"=>3, "Luke" => 4, "Pete" =>4, "Lola" => 1);
$max = max($testarr);
$only_max = array_filter($testarr, function($item) use($max){ return $item == $max; });
var_dump( $only_max );
Output:
array(2) {
["Luke"]=>
int(4)
["Pete"]=>
int(4)
}
Note that the closure function is referencing $max. As suggested by #devon, referencing the original array would make the code shorter & general, in exchange for calculation efficiency.
$only_max = array_filter($testarr,
function($item) use($testarr){
return $item == max($testarr);
});

This will get you where you need to go:
<?php
function less_than_max($element)
{
// returns whether the input element is less than max
return($element < 10);
}
$array1 = array("a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5);
$array2 = array("a" => 6, "b"=>7, "c"=>8, "d"=>9, "e"=>10, "f"=>11, "g"=>12);
$max = 3;
echo "Max:\n";
print_r(array_filter($array1, "less_than_max"));
echo "Max:\n";
print_r(array_filter($array2, "less_than_max"));
?>

Related

Rank keys of an associative array according to their values (error in function)

I want to rank the keys of an associative array in php based upon their values. (top to down as 1, 2, 3....). Keys having same value will have same rank.
Here function getRanks() is meant to return an array containing keys and the ranks (number).
I expect it to return like this (this is sorted value wise in descending)
Array
(
[b] => 1
[a] => 2
[d] => 3
[c] => 3
[e] => 4
)
There is issue in assigning the ranks (values) in the $ranks array which is to be returned.
What am I doing wrong? Do these loops even do something?
Code:
$test = array('a'=> 50, 'b'=>60, 'c'=>20, 'd'=>20, 'e'=>10);
$json = json_encode($test);
print_r(getRanks($json));
function getRanks($json) {
$tmp_arr = json_decode($json, TRUE);
$ranks = array();
uasort($tmp_arr, function($a, $b){
return $a == $b ? 0 : $a > $b ? -1 : 1; //descending
});
$keys = array_keys($tmp_arr); //after sorting
$ranks = array_fill_keys($keys, 0); //copy keys
$ranks[$keys[0]] = 1; //first val => rank 1
//------- WORKS FINE UNTIL HERE ------------------
// need to fix the ranks assignment
for($i=1; $i<count($keys)-1; $i++) {
for($j=$i; $j < count($keys)-1; $j++) {
if($tmp_arr[$keys[$j]] == $tmp_arr[$keys[$j+1]]) {
$rank[$keys[$j]] = $i;
}
}
}
return $ranks;
}
Your approach seems unnecessarily complicated. In my version I kept the json-related copying part of it but finished it off in a simpler way:
function getRanks($json) {
$tmp_arr = json_decode($json, TRUE);
asort($tmp_arr);. // sort ascending
$i=0; $lv=null;$ranks = array();
foreach ($tmp_arr as $k=>$v) {
if ($v>$lv){ $i++; $lv=$v;}
$ranks[$k]=$i;
}
return $ranks;
}
See the demo here: https://rextester.com/LTOA23372
In a slightly modified version you you can also do the ranking in a descending order, see here: https://rextester.com/HESQP10053
I've also tried with another approach.
I think it may not be the good solution because of high memory & CPU time consumption.
For small arrays (in my case) it works fine.
(I've posted because it may be an answer)
It creates array of unique values and fetches ranks accordingly.
$test = array('a'=> 50, 'b'=>60, 'c'=>20, 'd'=>20, 'e'=>10);
$json = json_encode($test);
print_r(getRanks($json));
function getRanks($json) {
$tmp_arr = json_decode($json, TRUE);
arsort($tmp_arr);
$uniq_vals = array_values(array_unique($tmp_arr)); // unique values indexed numerically from 0
foreach ($tmp_arr as $k => $v) {
$tmp_arr[$k] = array_search($v, $uniq_vals) + 1; //as rank will start with 1
}
return $tmp_arr;
}
This is the simple thing that you can do it by using php array function check example given below.
<?php
$fruits = array("d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple");
asort($fruits);
foreach ($fruits as $key => $val) {
echo "$key = $val\n";
}
?>

get the sum and difference of two associate array in php

I have 2 arrays.
arr1 =array('cat'=>5,'dog'=>2);
arr2 = array('cat'=>1,'dog'=>2);
I need to get the sum of 2 arrays and the difference of these arrays.
arr3 = array(cat =>6,dog =>4);
arr4 = array(cat =>4 ,dog =>0);
I tried USING array_merge,array_diff,array_combine
But nothing gives me what i need.
plz help
Assuming we have the same number of like keys in both arrays we can iterate through one or the other and find and work with the corresponding values belonging to the other identified by the same named keys.
<?php
$a1 = array('cat'=>5,'dog'=>2);
$a2 = array('cat'=>1,'dog'=>2);
foreach($a1 as $k => $v)
{
$add[$k] = $v + $a2[$k];
$sub[$k] = $v - $a2[$k];
}
var_dump($add, $sub);
Output:
array(2) {
["cat"]=>
int(6)
["dog"]=>
int(4)
}
array(2) {
["cat"]=>
int(4)
["dog"]=>
int(0)
}
You could always resolve the first problem with array_sum.
Second is more interesting, I'd solve it with an array_map. See it in action here
$subtracted = array_map(function ($x, $y) {
return $x - $y;
}, $arr1, $arr2);
$result = array_combine(array_keys($arr1), $subtracted);
Note that you can also solve the first problem by replacing - with + in the above example.
Also note that array_map tends to be generally more readable.
Simple foreach can do it, below example if some key is missing and just getting difference not in -ve Negative sign, the difference would be 4 not -4 for 1 cat - 5 cat
<?php
$arr1 =array('cat'=>5,'dog'=>2);
$arr2 = array('cat'=>1,'dog'=>2);
$sum= [];
$sub= [];
foreach(array_merge($arr1,$arr2) as $k=>$v){
$a1 = $arr1[$k] ?? 0;
$a2 = $arr2[$k] ?? 0;
$sum[$k] = $a1 + $a2;
$sub[$k] = abs($a1 - $a2);
}
print_r($sum);
print_r($sub);
?>
Live Demo
With simple foreach loop
If some data exist only in single array

How to shuffle the arrays in for loop manually?

I'v written 2 codes to shuffle some arrays whitch are in a for loop
First:
$numbers = range(0, sizeof($array_id)-1);
shuffle($numbers);
foreach ($numbers as $number) {
$arr = array("user" => array("id" => $array_id[$number], "name" => $array_name[$number], "key" => $array_key[$number]));
}
echo json_encode($arr);
This one has a big problem and that's if the $number in one of the arrays equals to 5 it won't loop to put another result of $number in the that array, for example the result would be something like this:
{"user":{"id":["18","2","36"],"name":["alex","john"],"key":["159","228,"486,"852"]]}}
All of my arrays have 5 values in them and you can see it returned them defectively.I'll be thankful if anyone can tell me why when $number gets the max value in range by shuffle and array gets that $number it stocks?
Second:
function shuffle_assoc(&$array) {
if (shuffle($array)) {
return $array;
}else{
return FALSE;
}
}
for ($y=0; $y<sizeof($array_id); $y++) {
$arr = array("user" => array("id" => shuffle_assoc($array_id), "name" => shuffle_assoc($array_name), "key" => shuffle_assoc($array_key)));
}
echo json_encode($arr);
This one works fine But I want the id and name to be match I mean they shuffle the same(if $array_id[2] then array_name[2]) that's why I wrote the first code.anyway for this one if anyone knows how to make id and name shuffle the same I'll be appreciate that.(sorry if I had mistakes in my writing my first language isn't English but I love English :)
I'm not sure that I completely understood you, but
$numbers = range(0, 5);
// $number = array(0, 1, 2, 3, 4, 5)
All of my arrays have 5 values
It's
$array_id[0]
$array_id[1]
$array_id[2]
$array_id[3]
$array_id[4]
So you haven't $array_id[5]. I think you need $numbers = range(0, 4);
EDIT:
Once again, I'm not sure if you want this to happen.
<?php
$array_id = array(1,2,3,4,5);
$array_name = array('a','b','c','d','e');
$numbers = range(0, 4);
shuffle($numbers);
$arr = array();
foreach ($numbers as $number) {
$arr["id"][] = $array_id[$number];
$arr["name"][] = $array_name[$number];
}
$arr2 = array("user" => array("id" => $arr["id"], "name" => $arr["name"]));
echo json_encode($arr2);
?>

PHP: Concatinating two array values

I have two arrays:
array(1,2,3,4,5)
array(10,9,8,7,6)
Final array Needed:
array(0=>1:10,1=>2:9,2=>3:8,3=>4:7,4=>5:6)
I can write a custom function which would be quieck enough!! But i wanted to use a existing one so Is there already any function that does this in php? Pass the two input arrays and get the final array result? I read through the array functions but couldn't find any or combination of function that would provide me the result
No built in function but really there is nothing wrong with loop .. Just keep it simple
$c = array();
for($i = 0; $i < count($a); $i ++) {
$c[] = sprintf("%d:%d", $a[$i], $b[$i]);
}
or use array_map
$c = array_map(function ($a,$b) {
return sprintf("%d:%d", $a,$b);
}, $a, $b);
Live Demo
Try this :
$arr1 = array(1,2,3,4,5);
$arr2 = array(10,9,8,7,6);
$res = array_map(null,$arr1,$arr2);
$result = array_map('implode', array_fill(0, count($res), ':'), $res);
echo "<pre>";
print_r($result);
output:
Array
(
[0] => 1:10
[1] => 2:9
[2] => 3:8
[3] => 4:7
[4] => 5:6
)
See: http://php.net/functions
And especially: http://nl3.php.net/manual/en/function.array-combine.php
Also, I don't quite understand the final array result?
Do you mean this:
array (1 = 10, 2 = 9, 3 = 8, 4 = 7, 5 = 6)
Because in that case you'll have to write a custom function which loops through the both arrays and combine item[x] from array 1 with item[x] from array 2.
<?php
$arr1=array(1,2,3,4,5);
$arr2=array(10,9,8,7,6);
for($i=0;$i<count($arr1);$i++){
$newarr[]=$arr1[$i].":".$arr2[$i];
}
print_r($newarr);
?>
Use array_combine
array_combine($array1, $array2)
http://www.php.net/manual/en/function.array-combine.php

(PHP) Checking items in an array

I have an array like this:
Array(a,b,c,a,b)
Now, if I would like to check how many instances of "b" I can find in the array, how would I proceed?
See the documentation for array_count_values(). It seems to be what you are looking for.
$array = array('a', 'b', 'c', 'a', 'b');
$counts = array_count_values($array);
printf("Number of 'b's: %d\n", $counts['b']);
var_dump($counts);
Output:
Number of 'b's: 2
array(3) {
["a"]=> int(2)
["b"]=> int(2)
["c"]=> int(1)
}
Use array_count_values($arr). This returns an associative array with each value in $arr as a key and that value's frequency in $arr as the value. Example:
$arr = array(1, 2, 3, 4, 2);
$counts = array_count_values($arr);
$count_of_2 = $counts[2];
You can count the number of instances by using this function..
$b = array(a,b,c,a,b);
function count_repeat($subj, $array) {
for($i=0;$i<count($array);$i++) {
if($array[$i] == $subj) {
$same[] = $array[$i]; //what this line does is put the same characters in the $same[] array.
}
return count($same);
}
echo count_repeat('b', $b); // will return the value 2
Although there are some fancy ways, a programmer should be able to solve this problem using very basic programming operators.
It is absolutely necessary to know how to use loops and conditions.
$count = 0;
$letters= array("a","b","c","a","b");
foreach ($letters as $char){
if ($char == "b") $count = $count+1;
}
echo $count.' "b" found';
NOT a rocket science.

Categories