Calculate the highest duplicate integers of two associative arrays - php

Given 2 associative arrays:
$fruits = array ( "d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple" );
$fruits2 = array ( "e" => "lemon", "f" => "apple", "g" => "melon", "h" => "apple" );
I would like to do something like:
for ( $n = count($fruits), $i = 0; $i < $n; $i++)
{
$test = (bool) $fruits[$i] == $fruits2[$i];
}
This can not work as I am using associative array. What would be the best way to go to achieve that? (This loops is going to be ran intensity so I would like to keep it as light as possible)
EDIT to give more detail on what I am trying to do:
Here is a better example of what I am trying to achieve:
$array = array ( 1,2,3,4,3,2 );
$array2 = array ( 9,6,3,4,3,2 );
$counts = array_count_values( $words );
$counts2 = array_count_values( $words2 );
Given the arrays above I need to calculate which array as the highest duplicate integers. Imagine a poker game, comparing two hands that each contain duplicate cards, how to evaluate which set of duplicate (whether double, triple or quadruple ) as the highest value.

Use array array_values ( array $input ) function and compare them.
$value1=array_values($fruits);
$value2=array_values($fruits2);
for ( $i = 0; $i < count($value1); $i++)
{
$test[] = $value1[$i] == $value2[$i] ? TRUE : FLASE;
}

Got it working this way :
$n = count($fruits);
for ( $i = 0; $i < $n; $i++)
{
$cur_vals_1 = each ($fruits);
$cur_vals_2 = each ($fruits2);
$sum1 += $cur_vals_1['key'] * $cur_vals_1['value'];
...
}

You're probably chasing the wrong solution. To find the highest duplicate in an array I'd use this (PHP 5.3+ syntax):
max(array_keys(array_filter(array_count_values($array), function ($i) { return $i >= 2; })))
Do this for both arrays and compare which result is higher. Trying to compare both against each other at the same time is too convoluted.

You don't need the ternary operator.
Also, be careful with count() as it will fail if your array is null.
They also need to be equal lengths or you'll get an error.
if( is_array($value1) && is_array($value2) && count($value1)==count($value2) ) {
for ( $i = 0; $i < count($value1); $i++)
{
$test[] = ($value1[$i] == $value2[$i]);
}
}

Related

How do I write a function in PHP that takes an array and returns an array if any two values in the input array equal a targeted sum

function twoNumberSum($array,$targetSum) {
sort($array);
$left = 0;
$right = count($array) - 1;
while ($left < $right) {
$currentSum = $array[$left] + $array[$right];
if($currentSum == $targetSum) {
print_r([$array[$left], $array[$right]]);
} else if ($currentSum < $targetSum) {
$left += 1;
} else if ($currentSum > $targetSum) {
$right -= 1;
}
}
return [];
}
$numArray = [3,5,-4,8,11,1,-1,6];
$targetSum = 10;
twoNumberSum($numArray,$targetSum);
The Goal
My goal here is to use pointers to slowly work through the array on both ends, all the while adding the values at array[left] and array[right]. If the currentSum is less than the targetSum, the left pointer moves up by one. If the currentSum is greater than the targetSum, the right pointer goes down by one. If currentSum and targetSum are equal, the function returns an array of array[left] and array[right].
The Problem
For some reason, when I run the code with the above array and target value, with the expected output being (11, -1), I get the expected output, but it's repeated several times over. I actually wouldn't encourage you all to run this code on your machines. I'll include a screenshot of what I'm seeing. output from above code
What I've tried
I've tried exiting the function using the return keyword beneath where I'm calling the print_r function. And this works, but only to a certain degree. In the event that targetValue is equal to 4, in which case the expected output is (3,1) (5,-1), and (-4,8), the output only returns the last valid pair of integers rather than all of them.
Any help in figuring this out would be greatly appreciated.
cycle through the array, and for each element, cycle through the rest of the array to test sums.
function twoNumberSum ( $inputArray, $targetSum ) {
for ( $i = 0; $i < count( $inputArray ) - 1; $i++ ) {
for ( $e = $i + 1; $e < count( $inputArray ); $e++ ) {
if ( $inputArray[$i] + $inputArray[$e] == $targetSum ) return [];
}
}
return null;
}
$numArray = [3,5,-4,8,11,1,-1,6];
$targetSum = 10;
var_dump( twoNumberSum( $numArray, $targetSum ) );
To compare all elements of the array with each other, 2 loops are necessary. This solution uses 2 forech loops and returns all possible pairs that satisfy the condition. There is no need to manually create a copy of $inputArray as PHP forech works internally with copies.
function twoNumberSum ( $inputArray, $targetSum ) {
$res = [];
foreach($inputArray as $i => $firstVal){
array_shift($inputArray);
foreach($inputArray as $secVal){
if ( $firstVal + $secVal == $targetSum ) {
$res[] = [$firstVal,$secVal] ;
}
}
}
return $res;
}
$numArray = [3,5,-4,8,11,1,-1,6];
$targetSum = 4;
var_export( twoNumberSum( $numArray, $targetSum ) );
Output:
array (
0 =>
array (
0 => 3,
1 => 1,
),
1 =>
array (
0 => 5,
1 => -1,
),
2 =>
array (
0 => -4,
1 => 8,
),
)
Try self.

Find number of distinct pairs of numbers whose sum is equal to some 'K' - PHP

Given an array, I would like to display the count of distinct pairs of elements whose sum is equal to K -
I've written code as below, but I am unable to put array_diff to good use :\
<?PHP
function numberOfPairs($a, $k) {
$cnt = 0;
for($i=0; $i<count($a); $i++){
for($j=$i; $j<count($a); $j++){
if($a[$i]+$a[$j] == $k){
$arrRes[$i][0] = $a[$i];
$arrRes[$i][1] = $a[$j];
$cnt++;
}
}
}
sort($arrRes);
//print $cnt;
$d = $cnt;
for($i=0; $i<count($arrRes); $i++){
for($j=0; $j<count($arrRes); $j++){
$diff = array_diff($arrRes[$i], $arrRes[$j]);
if($diff == null)
$d += 1;
}
}
print $d;
}
$a = [6,6,3,9,3,5,1];
$k = 12;
numberOfPairs($a, $k);
?>
Here, the output arrays with sum equal to 12 are, i.e, the result of $arrRes is -
[0] => Array ( [0] => 3 [1] => 9 )
[1] => Array ( [0] => 6 [1] => 6 )
[2] => Array ( [0] => 6 [1] => 6 )
[3] => Array ( [0] => 9 [1] => 3 )
The count is 4, but the count should be 2, as (6,6) and (3,9) are the only distinct pairs.
You can simplify your solution, by using fact that arrays in php are hashmaps:
function numberOfPairs($a, $k) {
$used=[];
for ($i=0; $i<count($a); $i++)
for ($j=$i+1; $j<count($a); $j++) {
$v1 = min($a[$i], $a[$j]);
$v2 = max($a[$i], $a[$j]);
if ($k == $v1+$v2)
$used[$v1.'_'.$v2] = true;
}
return count($used);
}
$a = [6,6,3,9,3,5,1];
$k = 12;
echo numberOfPairs($a, $k);
You can create a flat array with used numbers and check so that you don't use them again with in_array.
function numberOfPairs($a, $k) {
$cnt = 0;
$used=[];
for($i=0; $i<count($a); $i++){
for($j=$i; $j<count($a); $j++){
if($a[$i]+$a[$j] == $k && !in_array($a[$i], $used) && !in_array($a[$i],$used)){
$arrRes[$i][0] = $a[$i];
$arrRes[$i][1] = $a[$j];
$used[] = $a[$i];
$used[] = $a[$j];
$used = array_unique($used);
$cnt++;
}
}
}
sort($arrRes);
//print $cnt;
// Not sure what the code below does, but I just left it the way it was.
$d = $cnt;
for($i=0; $i<count($arrRes); $i++){
for($j=0; $j<count($arrRes); $j++){
$diff = array_diff($arrRes[$i], $arrRes[$j]);
if($diff == null)
$d += 1;
}
}
print $d;
}
$a = [6,6,3,9,3,5,1];
$k = 12;
numberOfPairs($a, $k);
Try it here https://3v4l.org/lDe5V
Sort array and move indexes from both ends until they are not overlapped that gets O(n log n) instead of O(n^2) in accepted answer
function numberOfPairs($a, $k) {
sort($a);
$i = 0;
$j = count($a)-1;
// save last inseted array to avoid duplicates
$last = [];
while($i < $j) {
$s = $a[$i] + $a[$j];
if($s == $k) {
$t = [$a[$i++], $a[$j--]];
// Check for duplicate
if ($t != $last) {
$d[] = [$a[$i++], $a[$j--]];
$last = $t;
}
}
elseif($s > $k) $j--;
else $i++;
}
return $d;
}
demo
This is my method for finding distinct pairs of addends given an array and a target sum.
array_count_values() will reduce the input array size by condensing duplicate addends and storing them as keys (and their number of occurrences as values).
ksort() is called to ensure that the addends are processed in ascending order. This is crucial to avoid processing addends that are beyond the midpoint of the number set.
each iteration, store addends that are "less than or equal to" half of k AND have a matching addend.
when the addend multiplied by 2 is "greater than or equal to" k, do not continue to iterate.
Code: (Demo)
function numberOfPairs($a,$k){
$a=array_count_values($a); // enable use of the very fast isset() function and avoid iterating duplicates
ksort($a); // order so that only the lower values need to be iterated
foreach($a as $num=>$occur){
if(($double=$num*2)>=$k){ // we are at or past the middle
if($double==$k && $occur>1) $result[]=[$num,$k-$num]; // addends are equal and 2 exist, store before break
break;
}elseif(isset($a[$k-$num])){ // matching addend found, store & continue
$result[]=[$num,$k-$num];
}
}
var_export($result);
}
$a = [6,6,3,9,3,5,1];
$k = 12;
numberOfPairs($a,$k);
Output:
array (
0 =>
array (
0 => 3,
1 => 9,
),
1 =>
array (
0 => 6,
1 => 6,
),
)
array_count_values() is probably the most expensive function call in the snippet, but it sets up all subsequent processes to be fast, concise, direct, and logical (and I think, readable).

Creating, Accessing and understanding multidimensional arrays in php

I have implemented the following small example:
$nodeList;
for($i = 0; $i < 10;$i++) {
$nodeList[$i] = $i;
for($j = 0; $j < 3;$j++) {
$nodeList[$i][$j] = $j;
}
}
foreach($nodeList[0] as $nodeEl) {
print "NodeEl: ".$nodeEl." | ";
}
print nl2br("\n\r");
$testList = array
(
array(1,2,3),
array(4,5,6),
array(7,8,9),
array(10,11,12),
);
foreach($testList[0] as $testEl) {
print "TestEl: ".$testEl." | ";
}
Where the output for $nodeList is null (var_dump / print_r too) and the output for $testList is TestEl: 1 | TestEl: 2 | TestEl: 3, as expected.
In my understanding those two solutions should create roughly the same output - but instead there is no output for the first one at all. Because the second dimension of the array is not even created.
Reading up on http://php.net/manual/de/language.types.array.php creates the strong feeling that the [] operator is only for dereferencing / accessing of the array, but then again the docs provide a sample where they assign a value to a certain key the same way I do $arr["x"] = 42.
What is the difference between these two ways of array access?
How can I achieve filling a n-dimensional array in a way similar to the way I try to fill $nodeList?
You should make sure to have error reporting turned on, because warnings are generated for your code:
E_WARNING : type 2 -- Cannot use a scalar value as an array -- at line 7
This concerns the following statement:
$nodeList[$i] = $i;
If you want to create a 2D array, there is no meaning in assigning a number on the first level. Instead you want $nodeList[$i] to be an array. PHP does that implicitely (creating the array) when you access it with brackets [...], so you can just leave out the offending statement, and do:
for($i = 0; $i < 10;$i++) {
for($j = 0; $j < 3;$j++) {
$nodeList[$i][$j] = $j;
}
}
You can even leave out the $j in the last bracket pair, which means PHP will just add to the array using the next available numerical index:
for($i = 0; $i < 10;$i++) {
for($j = 0; $j < 3;$j++) {
$nodeList[$i][] = $j;
}
}
Adding a value at every level
If you really need to store $i at the first level of the 2D array, then consider using a more complex structure where each element is an associative array with two keys: one for the value and another for the nested array:
for($i = 0; $i < 10; $i++) {
$nodeList[$i] = array(
"value" => $i,
"children" => array()
);
for($j = 0; $j < 3;$j++) {
$nodeList[$i]["children"][] = array(
"value" => "$i.$j" // just example of value, could be just $j
);
}
}
$nodeList will be like this then:
array (
array (
'value' => 0,
'children' => array (
array ('value' => '0.0'),
array ('value' => '0.1'),
array ('value' => '0.2'),
),
),
array (
'value' => 1,
'children' => array (
array ('value' => '1.0'),
array ('value' => '1.1'),
array ('value' => '1.2'),
),
),
//...etc
);
You should write
<?php
$nodeList;
for($i = 0; $i < 10;$i++) {
for($j = 0; $j < 3;$j++) {
$nodeList[$i][$j] = $j;
}
}
foreach($nodeList[0] as $nodeEl) {
print "NodeEl: ".$nodeEl." | ";
}
You need to declare $nodeList as array like
$nodeList=array();
and for 2D array
$nodeList= array(array());

Replace non-specified array values with 0

I want to replace all array values with 0 except work and home.
Input:
$array = ['work', 'homework', 'home', 'sky', 'door']
My coding attempt:
$a = str_replace("work", "0", $array);
Expected output:
['work', 0, 'home', 0, 0]
Also my input data is coming from a user submission and the amount of array elements may be very large.
A bit more elegant and shorter solution.
$aArray = array('work','home','sky','door');
foreach($aArray as &$sValue)
{
if ( $sValue!='work' && $sValue!='home' ) $sValue=0;
}
The & operator is a pointer to the particular original string in the array. (instead of a copy of that string)
You can that way assign a new value to the string in the array. The only thing you may not do is anything that may disturb the order in the array, like unset() or key manipulation.
The resulting array of the example above will be
$aArray = array('work','home', 0, 0)
A loop will perform a series of actions many times. So, for each element in your array, you would check if it is equal to the one you want to change and if it is, change it. Also be sure to put quote marks around your strings
//Setup the array of string
$asting = array('work','home','sky','door')
/**
Loop over the array of strings with a counter $i,
Continue doing this until it hits the last element in the array
which will be at count($asting)
*/
for($i = 0; $i < count($asting);$i++){
//Check if the value at the 'ith' element in the array is the one you want to change
//if it is, set the ith element to 0
if ($asting[$i] == 'work' || $asting[$i] == 'home')
$asting[$i] = 0;
}
Here is some suggested reading:
http://www.php.net/manual/en/language.types.array.php
http://www.php.net/manual/en/language.control-structures.php
But if you are struggling on stuff such as looping, you may want to read some introductory programming material. Which should help you really understand what's going on.
A bit other and much quicker way, but true, need a loop:
//Setup the array of string
$asting = array('bar', 'market', 'work', 'home', 'sky', 'door');
//Setup the array of replacings
$replace = array('home', 'work');
//Loop them through str_replace() replacing with 0 or any other value...
foreach ($replace as $val) $asting = str_replace($val, 0, $asting);
//See what results brings:
print_r ($asting);
Will output:
Array
(
[0] => bar
[1] => market
[2] => 0
[3] => 0
[4] => sky
[5] => door
)
An alternative using array_map:
$original = array('work','home','sky','door');
$mapped = array_map(function($i){
$exclude = array('work','home');
return in_array($i, $exclude) ? 0 : $i;
}, $original);
you may try array_walk function:
function zeros(&$value)
{
if ($value != 'home' && $value != 'work'){$value = 0;}
}
$asting = array('work','home','sky','door','march');
array_walk($asting, 'zeros');
print_r($asting);
You can also give array as a parameter 1 and 2 on str_replace...
Just a small point to the for loop. Many dont realize the second comparing task is done every new iteration. So if it was a case of big array or calculation you could optimize loop a bit by doing:
for ($i = 0, $c = count($asting); $i < $c; $i++) {...}
You may also want to see http://php.net/manual/en/function.array-replace.php for original problem unless the code really is final :)
Try This
$your_array = array('work','home','sky','door');
$rep = array('home', 'work');
foreach($rep as $key=>$val){
$key = array_search($val, $your_array);
$your_array[$key] = 0;
}
print_r($your_array);
There are a few techniques on this page that make zero iterated function calls -- which is good performance-wise. For best maintainability, I recommend separating your list of targeted string as a lookup array. By modifying the original array values by reference, you can swiftly replace whole strings and null coalesce non-targeted values to 0.
Code: (Demo)
$array = ['work', 'homework', 'home', 'sky', 'door'];
$keep = ['work', 'home'];
$lookup = array_combine($keep, $keep);
foreach ($array as &$v) {
$v = $lookup[$v] ?? 0;
}
var_export($array);
Output:
array (
0 => 'work',
1 => 0,
2 => 'home',
3 => 0,
4 => 0,
)
You can very easily, cleanly extend your list of targeted strings by merely extending $keep.
If you don't want a classic loop, you can use the same technique without modifying the original array. (Demo)
var_export(
array_map(fn($v) => $lookup[$v] ?? 0, $array)
);
this my final code
//Setup the array of string
$asting = array('work','home','sky','door','march');
/**
Loop over the array of strings with a counter $i,
Continue doing this until it hits the last element in the array
which will be at count($asting)
*/
for($i = 0; $i < count($asting); $i++) {
//Check if the value at the 'ith' element in the array is the one you want to change
//if it is, set the ith element to 0
if ($asting[$i] == 'work') {
$asting[$i] = 20;
} elseif($asting[$i] == 'home'){
$asting[$i] = 30;
}else{
$asting[$i] = 0;
}
echo $asting[$i]."<br><br>";
$total += $asting[$i];
}
echo $total;

PHP-ILooping an arrays values through a larger array

I want to know if it is possible to take an array and insert the array's values into a bigger array, multiple times, so that the values of the smaller array fill up the bigger array.
Say array1 has values ([0 => 'a'],[1 => 'b'],[2 => 'c']), and array2 can hold 8 values. So, how would I take the values of array1 and insert them into array2 continuously until array2 runs out of space, so that array2 would have the values 'a','b','c','a','b','c','a','b'?
Thanks in advance,
~Hussain~
Essentially, you want to loop over and over the small array, adding each element to the new array until it has reached the desired size.
Consider this:
$max = 8;
$Orig_Array = array('a', 'b', 'c');
$Next_Array = array();
while True
{
foreach($Orig_Array as $v)
{
$Next_Array[] = $v;
if(count($Next_Array) >= $max)
break 2;
}
}
Assuming that your input array is indexed sequentially:
$len = count($input);
$output = array();
for ($i = 0; $i < MAX_SIZE; ++$i)
$output[] = $input[$i % $len];
$a = array('a','b','c');
$desired = 8;
$b = array();
for($i=0;$i<($desired/count($a))+1;++$i) $b = array_merge($b,$a);
array_splice($b,$desired);
Or
$a = array('a','b','c');
$desired = 8;
$b = array();
for($i=0;$i<$desired/count($a);++$i) $b = array_merge($b,$a);
for($i=0;$i<($desired-count($b)-1);++$i) $b[] = $a[$i];
The first one fills up an array so that it has at least desired number of elements and cuts off the rest. The second one fills up an array up the desired number of elements modulo original array size and adds up the rest.
Here's one using the input array's internal pointer, to keep things conceptually simple:
$input = array(1, 2, 3);
$size = 32;
$output = array();
for ( $i = 0; $i < $size; $i++ ) {
$curr = current($input);
if ( $curr === false ) {
reset($input);
$curr = current($input);
}
$output[] = $curr;
next($input);
}
print_r($output);die;

Categories