Monday 3 September 2018

PHP array_udiff to compare table values ​​with threshold (tolerance)

I need to compare database values with post values. If post values (decimal price) are within 2 cents threshold consider values equal. Result is array with 'real' difference. Arrays are consistent: same number of values, same keys.

$db_values =   array( "21" => 10.00, "22" => 20.00, "25" => 3.55);
$post_values = array( "21" => 9.98,  "22" => 20.01, "25" => 2.55 );

I'm trying to compare Absolute value to my tolerance value -- epsilon (Compare decimals in PHP) and array_udiff:
function epsilon_compare ($v1,$v2)
{
 $epsilon = 0.02;
 $diff = abs($v1 - $v2);

   if ($diff <= $epsilon)
    {
            return 0;
      //echo "numbers are equal";
      } else {
         return 1;
             }
    }

 print_r(array_udiff($post_values, $db_values, "epsilon_compare"));

gives correct result: Array ( [25] => 2.55 )
but when i use different array I get wrong result eg:
   $db_values =   array( "21" => 10.00, "22" => 20.00, "25" => 3.55);
   $post_values = array( "21" => 8.00,  "22" => 20.01, "25" => 2.55 );

In this case it gives:
   Array ( [21] => 8 [22] => 20.01 [25] => 2.55 )

Key [22] => 20.01 is listed but it is within the threshold so it shouldn't be in result set. I think I don't fully understand array_udiff. thanks.

The user supplied callback function is used for comparison. It must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.
Your function always returns 1 if the elements are unequal which results in diffrent (wrong) comparisons decisions.
<?php
function epsilon_compare ($v1,$v2)
{
    $epsilon = 0.02;
    $diff = $v1 - $v2;
    return abs($diff)<=$epsilon ? 0 : $diff;
}

$db_values =   array( "21" => 10.00, "22" => 20.00, "25" => 3.55);
$post_values = array( "21" => 8.00,  "22" => 20.01, "25" => 2.55 );
print_r(array_udiff($post_values, $db_values, "epsilon_compare"));

prints
Array
(
    [21] => 8
    [25] => 2.55
)


edit: using array_udiff_assoc
$db_values = array ( "1" => 7.55, "2" => 5.45, "3" => 5.45, "4" => 64.45, "5" => 54.75, "6" => 30.40, "7" => 56.99, "8" => 10.90, "9" => 60.85, "11" => 3.25, "12" => 13.05, "13" => 5.45, "14" => 8.00, "15" => 5.45, "16" => 13.05, "17" => 4.35 );
$post_values = array ( "1" => 7.55, "2" => 5.45, "3" => 5.45, "4" => 64.45, "5" => 54.75, "6" => 30.40, "7" => 56.99, "8" => 10.90, "9" => 60.85, "11" => 3.25, "12" => 13.05, "13" => 2.45, "14" => 8.00, "15" => 5.45, "16" => 12.05, "17" => 2.34 );
print_r(array_udiff_assoc($post_values, $db_values, "epsilon_compare"));

prints
Array
(
    [13] => 2.45
    [16] => 12.05
    [17] => 2.34
)

0 comments:

Post a Comment