0

I have 2 strings like this

$s1="32.56.86.90.23";

$s2="11.25.32.90.10";

I need to compare $s1 and $s2 and find if there are 2 or more numbers in common.

I am using this way

$s1_ar=explode(".",$s1);
$s2_ar=explode(".",$s2);
$result=array_diff($s1_ar,$s2_ar);
$rt1=5-count($result);
if($result>=2){ echo "YES"; } else {echo "no"; }

Since I need millions values of $s1 and $s2 and the code above seems to be slow, do you know alternative way to execute the work faster ?

gr68
  • 420
  • 1
  • 10
  • 25

4 Answers4

0

I tested it with the following code, one million times, less than 2 seconds on my 3 years old laptop.

Loop 1M times takes no time, most time is used for displaying.

Comment off the display, 1M loops, 0.816432 seconds

Saved the results into a file, ~13.564MB, 0.731708 seconds

ob_start();
$t1 = microtime();
for($i=1; $i<=1000000; $i++) {
  $s1="32.56.86.90.23";
  $s2="10.25.30.90.10";
  $s1_ar=explode(".",$s1);
  $s2_ar=explode(".",$s2);
  $result=array_diff($s1_ar,$s2_ar);
  $rt1=5-count($result);
  if($result>=2){ echo $i . " YES<br>"; } else {echo $i .  " no<br>"; }
}

$out = ob_get_contents();

ob_end_clean();

var_dump($out);

echo '<p>'.(microtime() - $t1).'</p>';
ild flue
  • 1,323
  • 8
  • 9
  • $result=count(array_intersect($s1_ar,$s2_ar); – splash58 Jan 31 '18 at 10:43
  • Php version? The OP suggests that $s1 and $s2 may be millions of values long, so perhaps better to test long strings rather than many iterations of the same calculation. – Progrock Jan 31 '18 at 16:22
  • `millions values of $s1 and $s2`, did not say the length of `$s1` and `$s2` are millions digits. Dealing with millions digits is much easier than loop million times. – ild flue Jan 31 '18 at 16:30
  • On the other hand, if `$s1` and `$s2` are million digits long, it is not necessary to process it, because it is for sure `there are 2 or more numbers in common`. – ild flue Jan 31 '18 at 16:35
  • No, for example: the set of negative integers and the set of positive integers are both infinite and have no number in common. – Progrock Jan 31 '18 at 23:19
0

I thought of a way to solve this in a 2*n complexity: We loop one list and create an associative array from it's elements (LIST c) then we loop the second list and look up if the list c contains such an index/key ( c[element] ). This shall be very light weighted :

$commons = 0;

$s1_fliped = array_flip($s1_ar)

foreach($s2_ar as $s2_el){
    if ( isset($s1_fliped[$s2_el]) ){
        $commons ++;
    }
    if($commons >=2) break;
});
Anatol Bivol
  • 890
  • 7
  • 20
  • 1
    You could array_flip instead of your first foreach. And you can bail out (break) of your second loop as soon as you have 2 numbers in common. – Progrock Jan 31 '18 at 11:54
0

Try this.

$s1="32.56.86.90.23";

$s2="11.23.32.90.10";
$s1_ar=explode(".",$s1);
$s2_ar=explode(".",$s2);
//assuming $s1_ar and $s2_ar both has unique values if not please make them unique 
$result_array = array();
$hasMatch = 0;
for($i = 0; $i < count($s1_ar) && $i < count($s2_ar); $i++){

    if(!isset($result_array[$s1_ar[$i]])){
        $result_array[$s1_ar[$i]] = 1;
    }else{
     $result_array[$s1_ar[$i]]++;
    }
    if(!isset($result_array[$s2_ar[$i]])){
        $result_array[$s2_ar[$i]] = 1;
    }else{
      $result_array[$s2_ar[$i]]++;
    }

} 

foreach($result_array as $result){
    if($result >=2) $hasMatch++;
}
if($hasMatch >= 2)
     echo "YES";
else
     echo "NO";

I think it will solve your purpose.

0

Looking at: php array_intersect() efficiency

There's mention that array_intersect_key may be more efficient. But really it would be nice to have data and versions to compare results.

$s1 = "2.3.5.7.9.11.13.17";
$s2 = "2.3.4.5.6";

$s1 = array_flip(explode('.', $s1));
$s2 = array_flip(explode('.', $s2));

echo count(array_intersect_key($s1, $s2))>=2 ? 'yes' : 'no';

Output:

yes
Progrock
  • 7,373
  • 1
  • 19
  • 25