PHP: different elements between two arrays - php

I have two different arrays like this
$array1 = [1, 2, 8, 10];
$array2 = [2, 4, 6, 8, 10, 15, 1];
I want to get the common elements and uncommon elements between them.
I almost figured out how to get the common ones as the code below but I can't get uncommon elements.
for($x = 0; $x < count($array1); $x++) {
for($z = 0; $z < count($array2); $z++) {
if ( $array1[$x] == $array2[$z] ) {
$array3 = $array1[$x];
print_r($array3);
} elseif ($array1[$x] !== $array2[$z]) {
// code...
}
}
}
How to get those uncommon or different elements between the two arrays without using a built-in PHP method then output them in a new array.

You can get the uncommon elements by using in_array() function
<?php
$array1 = [1, 2, 8, 10];
$array2 = [2, 4, 6, 8, 10, 15, 1];
$result = [];
for($i = 0;$i < sizeof($array2);$i++){
if(!in_array($array2[$i],$array1)){
$result[] = $array2[$i];
}
}
?>
Output
Array
(
[0] => 4
[1] => 6
[2] => 15
)

Related

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, ['']))

Get all possible pairs of n elements without duplicates with PHP

What I need
I need all possible pairs of n elements without duplicates. Let's say I've these arrays:
$arr1 = [2, 4, 6, 7];
$arr2 = [6, 5, 4, 11];
$arr3 = [22, 1, 5, 8];
$final = [
'a' => $arr1,
'b' => $arr2,
'c' => $arr3
];
What I now need is:
$pairs = [
'ab' => [$arr1, $arr2],
'ac' => [$arr1, $arr3],
'bc' => [$arr2, $arr3]
];
What I got
I come until this point:
function getPairs($array) {
$n = count($array);
$finalArray = [];
$i = 0;
foreach ($array as $a) {
for ($x = $n-1; 0 <= $x; $x--) {
if ($i != $x) {
$finalArray[] = [$array[$i], $array[$x]];
}
}
$i++;
}
return $finalArray;
}
And then:
$arr1 = [2, 4, 6, 7];
$arr2 = [6, 5, 4, 11];
$arr3 = [22, 1, 5, 8];
$merged = [$arr1, $arr2, $arr3];
$pairs = getPairs($merged);
There are two problems with my approach:
The loop produces $x = 0, $i = 1 and later $i = 1, $x = 0, which results and a duplicated array.
I don't get the keys (ab, ac, cb) with this.
Similiar to this question but with array keys: Get all the combinations of N elements of multidimensional array
To avoid duplicates, guarantee that one member of the pair always has the "lower" key. This will avoid getting pairs ac and ca.
To get the letter keys you want, use array_keys() to extract the keys from the original arrays.
function getPairs($array) {
$n = count($array);
$keys = array_keys($array);
$finalArray = [];
$i = 0;
foreach ($array as $a) {
for ($x = $n-1; $i < $x; $x--) {
$key1 = $keys[$i];
$key2 = $keys[$x];
$finalArray[$key1.$key2] = [$array[$key1], $array[$key2]];
}
$i++;
}
return $finalArray;
}
Live demo
This code should work if I understand the task properly:
$a = [[2, 4, 6, 7],[6, 5, 4, 11],[22, 1, 5, 8]];
$result = [];
$n = count($a);
for($i = 0; $i < $n-1; $i++) {
for($j = $i+1; $j < $n; $j++) {
$result[(string)$i.(string)$j] = [$a[$i], $a[$j]];
}
}
print_r($result);
Here is a "hybrid" of the other two answers:
$arr1 = [2, 4, 6, 7];
$arr2 = [6, 5, 4, 11];
$arr3 = [22, 1, 5, 8];
$final = [
'a' => $arr1,
'b' => $arr2,
'c' => $arr3
];
$n = count($final);
$keys = array_keys($final);
$pairs = [];
for($i = 0; $i < $n-1; $i++) {
for($j = $i+1; $j < $n; $j++) {
$pairs[$keys[$i] . $keys[$j]] = [$final[$keys[$i]], $final[$keys[$j]]];
}
}
print_r($pairs);

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);
?>

PHP Array Combine and Sum

I have multiple arrays, that get generated when a for loop completes. Now I need to get the total of all these arrays together, but in order, for instance:
array1(2, 4, 6, 8, 10)
array2(2, 4, 6, 8, 10)
I need to add the 2's together, the 4's etc etc
Then put them into another array.
Some combination of array_combine and array_sum seems to be the solution but I can't figure it out.
Any help is greatly appreciated.
You could do this without any php function except count,
$limit = count($array1);
for ($i = 0; $i < $limit; $i++) {
$array_res[$i] = $array1[$i] + $array2[$i];
should work. This will combine your two arrays and add them in the same order. But be sure you used sort or ksort on both of your arrays before if you're not sure they are in the same order.
1st stlye
$a1 = array(
"a" => 2
,"b" => 0
,"c" => 5
);
$a2 = array(
"a" => 3
,"b" => 9
,"c" => 7
,"d" => 10
);
$a3 = array_merge($a1, $a2);
print_r($a3);
2nd style
$a3 = $a1;
foreach($a2 as $k=>$v) {
if(array_key_exists($k,$a3))
$a3[$k] + = $v;
else
$a3[$k] = $v;
}
You should use array_map():
$arr1 = array(2, 4, 6, 8, 10);
$arr2 = array(1, 2, 3, 4, 5);
$arr3 = array_map(
function($foo, $bar){
return $foo+$bar;
},
$arr1, $arr2
);
print_r($arr3); // outputs:
Array
(
[0] => 3
[1] => 6
[2] => 9
[3] => 12
[4] => 15
)
You can do something like this
$a = array(2, 4, 6, 8, 10);
$b = array(2, 4, 6, 8, 10);
$c = array_map("test", $a, $b);
function test($a, $b) {
return $a + $b;
}
print_r($c);
As far as I understand your question You want sum of all the similar digits in both the array:
<?php
$array1= array(2, 4, 6, 8, 10);
$array2=array(2, 4, 6, 8, 10);
$array_sum=array();
foreach($array1 as $key1=>$val1)
{
$sum=0;
foreach($array2 as $key2 => $val2)
{
if($val1==$val2)
{
$sum=$sum+$val1;
}
}
$array_sum[]=$sum;
}
print_r($array_sum);
?>

Help with For Loop. Values repeating

$teams = array(1, 2, 3, 4, 5, 6, 7, 8);
$game1 = array(2, 4, 6, 8);
$game2 = array();
if teams[x] is not in game1 then insert into game2
for($i = 0; $i < count($teams); $i++){
for($j = 0; $j < count($game1); $j++){
if($teams[$i] == $game1[$j]){
break;
} else {
array_push($game2, $teams[$i]);
}
}
}
for ($i = 0; $i < count($game2); $i++) {
echo $game2[$i];
echo ", ";
}
Im expecting the result to be:
1, 3, 5, 7,
However, im getting:
1, 1, 1, 1, 3, 3, 3, 3, 4, 5, 5, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 8,
How can i improve this? Thanks
Others have already answered on how to use array_diff.
Reason why your existing loop does not work:
if($teams[$i] == $game1[$j]){
// this is correct, if item is found..you don't add.
break;
} else {
// this is incorrect!! we cannot say at this point that its not present.
// even if it's not present you need to add it just once. But now you are
// adding once for every test.
array_push($game2, $teams[$i]);
}
You can use a flag to fix your existing code as:
for($i = 0; $i < count($teams); $i++){
$found = false; // assume its not present.
for($j = 0; $j < count($game1); $j++){
if($teams[$i] == $game1[$j]){
$found = true; // if present, set the flag and break.
break;
}
}
if(!$found) { // if flag is not set...add.
array_push($game2, $teams[$i]);
}
}
Your loop doesn't work because every time the element from $teams is not equal to the element from $game1, it adds the $teams element to $game2. That means each element is being added to $game2 multiple times.
Use array_diff instead:
// Find elements from 'teams' that are not present in 'game1'
$game2 = array_diff($teams, $game1);
You can use PHP's array_diff():
$teams = array(1, 2, 3, 4, 5, 6, 7, 8);
$game1 = array(2, 4, 6, 8);
$game2 = array_diff($teams,$game1);
// $game2:
Array
(
[0] => 1
[2] => 3
[4] => 5
[6] => 7
)

Categories