PHP Array: Calculate difference among values in same array - php

I am trying to compute the difference between all values in an array and store them (the differences) in a single array.
An ideal example would be something like this:
<?php
$data = array('1', '5', '12');
// Compute the difference between each value with another value.
?>
And then I like to have the following results in an array:
4, 11, 7
How can I achieve it?

try this
$data = array('1', '5', '12');
$differences=[];
for($i=0;$i<count($data);$i++){
for($j=$i+1;$j<count($data);$j++){
$differences[]=abs($data[$i]-$data[$j]);
}
}
print_r($differences);
results in
Array
(
[0] => 4
[1] => 11
[2] => 7
)

Try by having double for loops one for iterating current array and another to start comparing and store it in result array.
I am not very sure about your output as information is less but you can try as follow:
var a= ["1","5","12"]
for(i=0;i<3;i++){for(j=0;j<3;j++){if(i>j)console.log(a[i]-a[j])}}

Check this https://3v4l.org/9oiqs
$data = [1, 5, 12, 15, 20, 25,];
function getDifferences($aValues)
{
$aDiff = [];
$iSize = count($aValues);
for ($i = 0; $i < $iSize; $i++)
{
for ($j = $i + 1; $j < $iSize; $j++)
{
$aDiff[$aValues[$i]][] = abs($aValues[$i] - $aValues[$j]);
}
}
return $aDiff;
}
function printDifferences($aValues){
foreach ($aValues as $iNumber => $aDiffs){
echo "Differences for $iNumber: " . implode(', ', $aDiffs) . PHP_EOL;
}
}
$aDiff = getDifferences($data);
printDifferences($aDiff);
Result
Differences for 1: 4, 11, 14, 19, 24
Differences for 5: 7, 10, 15, 20
Differences for 12: 3, 8, 13
Differences for 15: 5, 10
Differences for 20: 5

Related

Loop through array of values and sort

I would like you to help me with an algorithm in PHP that can loop through an array of values, sort them and print non-duplicates.
Here is the code I wrote. I want to do it with only loop and if else statement. I would appreciate any help in achieving this. Thanks
$input_array = [3, 5, 7, 7, 8, 3, 1, 9, 9, 9, 0, 2, 4, 8, 0, 12, 5, 8, 2];`
$count_array = count($input_array); // count the array`enter code here`
for($i = 0; $i < $count_array; $i++){ //loop through the array 1st time
$check_array = false;
//sort array
for($j = $i+1; $j < $count_array; $j++){
if($input_array[$i] > $input_array[$j]){
$non_duplicates = $input_array[$i];
$input_array[$i] = $input_array[$j];
$input_array[$j] = $non_duplicates;
}
else if($input_array[$i] == $input_array[$j] &&( $i != $j)){
$check_array = true;
break;
}
else{
$input_array[$i] != $input_array[$j];
}
}
if(!$check_array){
echo($input_array[$i]. ', ');
}
}
You can do it with 2 for cycles where the first cycle is for the first element and the 2nd cycle is always in the next position, this will help to always check if the first number is less than the second. You create a temporary variable where you store the value of the first number and you pass the value of the second number to the variable of the first one, later the temporary one that you had stored you pass it to the variable of the second number (with this you got to invert the values of one to the other).
As this is ordering them, later an if is made where it is verified if they are equal, in case of being equal a unset() is made to eliminate that data of the array.
// Array of values
$input_array = [3, 5, 7, 7, 8, 3, 1, 9, 9, 9, 0, 2, 4, 8, 0, 12, 5, 8, 2];
// count the length of array
$count = count($input_array);
// order array and remove duplicates
for ($i = 0; $i < $count; $i++) {
for ($j = $i + 1; $j < $count; $j++) {
// order array
if ($input_array[$i] < $input_array[$j]) {
$temp = $input_array[$i];
$input_array[$i] = $input_array[$j];
$input_array[$j] = $temp;
}
// delete duplicates
if ($input_array[$i] == $input_array[$j]) {
unset($input_array[$j]);
}
}
}
// Return an array with elements in reverse order
$input_array = array_reverse($input_array);
You get something like this:
Dump => array(9) {
[0] => int(1)
[1] => int(2)
[2] => int(3)
[3] => int(4)
[4] => int(7)
[5] => int(5)
[6] => int(8)
[7] => int(9)
[8] => int(12)
}

How to average columns of data from multiple, flat arrays?

Let's say I have 4 arrays with the same amount of values in each:
$array1 = array(0, 7, 5, 0);
$array2 = array(2, 6, 10, 0);
$array3 = array(4, 8, 15, 10);
$array4 = array(6, 7, 20, 10);
I want to count the average for all 4 of these arrays for each index. So I should get something like this:
array(3, 7, 12.5, 5);
For more dynamically usage lets say for example 6 arrays or more, you can use this code:
$all_arrays = [
array(0, 7, 5, 0),
array(2, 6, 10, 0),
array(4, 8, 15, 10),
array(6, 7, 20, 10),
array(1, 2, 3, 4),
array(5, 6, 7, 8),
// more arrays
];
$each_array_count = count($all_arrays[0]); // 4
$all_arrays_count = count($all_arrays); // 6
$output = [];
for ($i = 0; $i < $each_array_count; $i++) {
for ($j=0; $j < $all_arrays_count; $j++) {
$output[$i] += $all_arrays[$j][$i] / $all_arrays_count;
}
}
echo "<pre>";
var_dump($output);
Output: (Demo)
Warning: Undefined array key 0 in /in/E783F on line 20
Warning: Undefined array key 1 in /in/E783F on line 20
Warning: Undefined array key 2 in /in/E783F on line 20
Warning: Undefined array key 3 in /in/E783F on line 20
<pre>array(4) {
[0]=>
float(3)
[1]=>
float(6)
[2]=>
float(10)
[3]=>
float(5.333333333333333)
}
Fully Dynamic Function:
I took on the task of building a fully dynamic function where you can input as many arrays as you want. I also added a null check as seen in the example below just in case you need to skip a value inside an array.
Function:
# The three dots (...) allow for ANY amount of
# arrays to be inputted into the function
#
# Theoretically you can put 100 different arrays if you wanted
# e.g. arrayAverage($a1, $a2, $a3, $a4, $a5, $a6, ...etc)
function arrayAverage(...$array){
# Add each of the values you want to average out into
# separate temporary arrays for easy manageability.
# For this instance, the first value of the 4 arrays
# will be added to its own array, then the second
# value of the 4 arrays will be added to its own array,
# and so on and so on...
foreach($array as $arr){
for($i = 0; $i < count($arr); $i++){
if(!is_null($arr[$i])) $temparr[$i][] = $arr[$i];
}
}
# Now we can get the average of each of those arrays we created
# and put them into the "$averages" array, to be returned at the end
for($j = 0; $j < count($temparr); $j++){
$averages[] = array_sum($temparr[$j]) / count($temparr[$j]);
}
# Returns the averages in said array
return $averages;
}
Usage/Example:
# Arrays do NOT need the same number of values/keys as shown in "$array2"
$array1 = array(0, 7, 5, 0);
$array2 = array(2, 6, 10, 0, 100);
$array3 = array(4, 8, 15, 10);
$array4 = array(6, 7, 20, 10);
# Example on how to skip values just in case the need arises
# (So our averages won't be affected by having an extra number)
$array5 = array(null, null, null, null, 300);
$averages = arrayAverage($array1, $array2, $array3, $array4, $array5);
var_export($averages);
Output:
[3, 7, 12.5, 5, 200]
Live Sandbox Demo:
https://onlinephp.io/c/bb513
Here is a simple solution but you can generalize it further and make it generic but it will work for now. It can be updated accordingly:
NOTE: Assuming the count of array are same as you have mentioned
$result = [];
for ($i = 0; $i < count($array1); $i++) {
$result [] = ($array1[$i] + $array2[$i] + $array3[$i] + $array4[$i]) / count($array1);
}
dd($result);
Another approach:
$arrays = [$array1, $array2, $array3, $array4];
$result = [];
for ($i = 0; $i < count($array1); $i++) {
$result[] = array_sum(array_column($arrays, $i)) / count($arrays);
}
Working example.
For a sleek, functional-style snippet, use array_map() to "transpose" the rows of data. This means that columns of data will be passed to the custom function. From there, perform the averaging math.
Code: (Demo)
$array1 = [0, 7, 5, 0];
$array2 = [2, 6, 10, 0];
$array3 = [4, 8, 15, 10];
$array4 = [6, 7, 20, 10];
var_export(
array_map(
fn() => array_sum(func_get_args()) / func_num_args(),
$array1,
$array2,
$array3,
$array4
)
);
// fn(...$col) => array_sum($col) / count($col), would also work
Output:
array (
0 => 3,
1 => 7,
2 => 12.5,
3 => 5,
)
Note, this technique will fill gaps in the columns with null (counting as 0) when arrays are not all of the same length: Demo.
If your input array was a single multi-dimensional array, you could use the spread operator to unpack it into array_map().
var_export(array_map(fn() => array_sum(func_get_args()) / func_num_args(), ...$arrays));
To prevent null values from skewing the calculations, filter them before doing the math: Demo.
var_export(
array_map(
fn(...$col) => array_sum($col) / count(array_filter($col, fn($v) => !is_null($v))),
...$arrays
)
);
// or: fn(...$col) => array_sum($col) / count(array_diff($col, ['']))

Map an array of values to an array of each value's rank in the array

I have a array like this:
$row_arr_1=array(7,9,5,10);
now I want to get the result array like this:
$row_arr_2=array(3,2,4,1);
Explanation:
As 10 is the largest value in row_arr_1, then it will be replaced with value 1.
Similarly, as 9 is the 2nd highest value of row_arr_1, then it will be replaced by 2 and so on.
I tried to sort the values of row_arr_1 but the position is changed.
How
can i get my desired result?
It can be done using rsort() and array_search()
$row_arr_1=array(7,9,5,10);
$row_copy = $row_arr_1;
$row_arr_2 = array();
rsort($row_copy);
foreach($row_arr_1 as $val) {
$row_arr_2[] = array_search($val, $row_copy) + 1;
}
print_r($row_arr_2);
https://eval.in/990078
You can use arsort() to sort the array while preserving keys, and use those keys for your array via array_keys():
$row_arr_1 = array(7,9,5,10);
$row_arr_1_backup = $row_arr_1;
arsort($row_arr_1_backup);
$row_arr_2 = array_keys($row_arr_1_backup);
asort($row_arr_2);
$row_arr_2 = array_keys($row_arr_2);
array_walk($row_arr_2, function(&$item, &$key) {
$item = $item + 1;
});
You have to duplicate the original array, since arsort will sort the actual array it points to, rather than returning a new array.
$row_arr_1_old = array(7, 9, 5, 10);
$row_arr_1 = array(7, 9, 5, 10);
rsort($row_arr_1);
$test = [];
foreach ($row_arr_1_old as $key => $value) {
$test[] = array_search($value, $row_arr_1);
}
print_r($test);
For best efficiency try to reduce total function calls; this especially means minimizing / eliminating iterated function calls.
This is my slightly more efficient version of ahsan's answer.
Code: (Demo)
$copy = $arr = [7, 9, 5, 10];
rsort($arr); // generates: [10, 9, 7, 5]
$flipped = array_flip($arr); // generates: [10 => 0, 9 => 1, 7 => 2, 5 => 3]
foreach($copy as $v) {
$result[] = ++$flipped[$v]; // adds one to each accessed value from $flipped
}
var_export($result);
Output:
array (
0 => 3,
1 => 2,
2 => 4,
3 => 1,
)

Merge two flat arrays and omit values from one array when the other array has more occurrences of the same value

I want to merge every element of two arrays, BUT if a value is in both arrays, then only add the values from the array which has the biggest amount of that element. The result array does not need to be sorted in any special way, but I did it here for readability.
Sample input:
$array1 = [1, 4, 7, 3, 3, 3];
$array2 = [4, 0, 3, 4, 9, 9];
Desired result:
[0, 1, 3, 3, 3, 4, 4, 7, 9, 9]
//a2 a1 a1 a1 a1 a2 a2 a1 a2 a2
Note, this will be used on big arrays, with unknown integer values. Is there a good way to do this that doesn't require too much time/processing power?
Try this:
<?php
$array1 = [1, 4, 7, 3, 3, 3];
$array2 = [4, 0, 3, 4, 9, 9];
function min_merge($arr1, $arr2) {
$arr1 = array_count_values($arr1);
$arr2 = array_count_values($arr2);
foreach ($arr2 as $index => $arr)
if (!isset($arr1[$index]) || $arr > $arr1[$index])
$arr1[$index] = $arr;
foreach ($arr1 as $index => $arr)
for ($i = 0; $i < $arr; $i++)
$final[] = $index;
return $final;
}
print_r(min_merge($array1, $array2));
Output:
Array (
[0] => 1
[1] => 4
[2] => 4
[3] => 7
[4] => 3
[5] => 3
[6] => 3
[7] => 0
[8] => 9
[9] => 9
)
Unsorted, but it contains all the numbers from [0, 1, 3, 3, 3, 4, 4, 7, 9, 9].
$count[0] = array_count_values($arr1);
$count[1] = array_count_values($arr2);
$out = array();
array_map(function($e) use(&$out, $count){
$n1 = (isset($count[0][$e])) ? $count[0][$e] : 0;
$n2 = (isset($count[1][$e])) ? $count[1][$e] : 0;
$next = ($n2 > $n1) ? array_fill(0, $n2, $e) : array_fill(0, $n1, $e);
$out = array_merge($out, $next);
}, array_keys($count[0] + $count[1]));
print_r($out);
My modernized rewrite of #DaveChen's answer using PSR-12 coding standards and eliminating single-use declarations. This approach uses one loop to determine the greater count for numbers shared by both value-count arrays, then a second loop to populate the result array. (Demo)
$counts1 = array_count_values($array1);
foreach (array_count_values($array2) as $number => $count) {
if ($count > ($counts1[$number] ?? 0)) {
$counts1[$number] = $count;
}
}
$result = [];
foreach ($counts1 as $number => $count) {
array_push($result, ...array_fill(0, $count, $number));
}
var_export($result);
My modernized rewrite of #Expedito's answer which does not abuse the array_map() (when array_map()'s return value is not used, use array_walk() for functional style programming), uses a foreach() loop to eliminate variable scope issues, and generally implements D.R.Y. techniques. (Demo)
$counts1 = array_count_values($array1);
$counts2 = array_count_values($array2);
$result = [];
foreach ($counts1 + $counts2 as $num => $cnt) {
array_push(
$result,
...array_fill(
0,
max($counts1[$num] ?? 0, $counts2[$num] ?? 0),
$num
)
);
}
var_export($result);
And I wanted to add a new approach of my own, despite the fact that it may or may not perform better than the other two snippets. The script makes one pass over the first value count arrays to populate a temporary array which demands which numbers from the first array should be represented in the result array. Then it isolates value intersections from the first array, value differences from the second array, then merges them. (Demo)
$counts1 = array_count_values($array1);
$counts2 = array_count_values($array2);
$keepFrom1 = array_keys(
array_filter(
$counts1,
fn($count, $number) => ($counts2[$number] ?? 0) <= $count,
ARRAY_FILTER_USE_BOTH
)
);
var_export(
array_merge(
array_intersect($array1, $keepFrom1),
array_diff($array2, $keepFrom1)
)
);
probably not the most optimized but
<?php
$one=[1, 4, 7, 3, 3, 3];
$two=[4, 0, 3, 4, 9, 9];
sort($one);
sort($two);
foreach($one as $el)
{
$combined[]=$el;
if (array_search($el,$two))
{
unset($two[array_search($el,$two)]);
}
}
foreach($two as $el)
{
$combined[]=$el;
}
sort($combined);
print_r($combined);
?>

Counting occurrence of specific value in an Array with PHP [duplicate]

This question already has answers here:
Count number of values in array with a given value
(8 answers)
Closed 3 years ago.
I am trying to find a native PHP function that will allow me to count the number of occurrences of a particular value in an array. I am familiar with the array_count_values() function, but that returns the count of all values in an array. Is there a function that allows you to pass the value and just return the instance count for that particular value? For example:
$array = array(1, 2, 3, 3, 3, 4, 4, 5, 6, 6, 6, 6, 7);
$instances = some_native_function(6, $array); //$instances will be equal to 4
I know how to create my own function, but why re-invent the wheel?
function array_count_values_of($value, $array) {
$counts = array_count_values($array);
return $counts[$value];
}
Not native, but come on, it's simple enough. ;-)
Alternatively:
echo count(array_filter($array, function ($n) { return $n == 6; }));
Or:
echo array_reduce($array, function ($v, $n) { return $v + ($n == 6); }, 0);
Or:
echo count(array_keys($array, 6));
This solution may be near to your requirement
$array = array(1, 2, 3, 3, 3, 4, 4, 5, 6, 6, 6, 6, 7);
print_r(array_count_values($array));
Result:
Array
( [1] => 1 ,[2] => 1 , [3] => 3, [4] => 2,[5] =>1, [6] => 4, [7] => 1 )
for details.
As of PHP 5.4.0 you can use function array dereferencing for the index [6] of the array resulting from array_count_values():
$instances = array_count_values($array)[6];
So to check and assign 0 if not found:
$instances = array_count_values($array)[6] ?? 0;
Assume we have the following array:
$stockonhand = array( "large green", "small blue", "xlarge brown", "large green", "medieum yellow", "xlarge brown", "large green");
1) Copy and paste this function once on top your page.
function arraycount($array, $value){
$counter = 0;
foreach($array as $thisvalue) /*go through every value in the array*/
{
if($thisvalue === $value){ /*if this one value of the array is equal to the value we are checking*/
$counter++; /*increase the count by 1*/
}
}
return $counter;
}
2) All what you need to do next is to apply the function every time you want to count any particular value in any array. For example:
echo arraycount($stockonhand, "large green"); /*will return 3*/
echo arraycount($stockonhand, "xlarge brown"); /*will return 2*/
Say I have an array like this:
$array = array('', '', 'other', '', 'other');
$counter = 0;
foreach($array as $value)
{
if($value === '')
$counter++;
}
echo $counter;
This gives the number of times ' ' is repeating in the array
This is exactly what you looking for
<?php
$MainString = 'Yellow Green Orange Blue Yellow Black White Purple';
$FinderString = 'Yellow Blue White';
$mainArray = explode(" ", $MainString);
$findingArray = explode(" ", $FinderString);
$count = 0;
$eachtotal = array_count_values($mainArray);
foreach($findingArray as $find){
$count += $eachtotal[$find];
}
echo $count;
?>

Categories