bikey77
bikey77

Reputation: 6672

PHP - How do I partially compare elements in 2 arrays

I have 2 arrays:

$arr1 = array('Test', 'Hello', 'World', 'Foo', 'Bar1', 'Bar'); and
$arr2 = array('hello', 'Else', 'World', 'Tes', 'foo', 'BaR1', 'Bar'); 

I need to compare the 2 arrays and save the position of the matching elements to a 3rd array $arr3 = (3, 0, 2, 4, 5, 6); //expected result, displaying position of matching element of $arr1 in $arr2.

By 'matching' I mean all elements that are identical (ex. World), or partially the same (ex. Test & Tes) and also those elements that are alike but are in different case (ex. Foo & foo, Bar & bar).

I've tried a series of combinations and of various functions without success, using functions like array_intersect(), substr_compare(), array_filter() and more. I'm not asking for the exact solution, just something to get me on the right track because i'm going around in circles all afternoon.

Upvotes: 1

Views: 1068

Answers (4)

AbsoluteƵERØ
AbsoluteƵERØ

Reputation: 7880

I came up with this to account for duplicates. It returns both keys and both values so you can compare to see if it's working properly. To refine it, you can just comment out the lines setting the values you don't need. It matches all cases.

<?php

$arr1 = array('Test', 'Hello', 'World', 'Foo', 'Bar1', 'Bar');
$arr2 = array('hello', 'Else', 'World', 'Tes', 'foo', 'BaR1', 'Bar');

$matches = array();
//setup the var for the initial match
$x=0;
foreach($arr1 as $key=>$value){

$searchPhrase = '!'.$value.'!i';

    //Setup the var for submatching (in case there is more than one)
    $y=0;
    foreach($arr2 as $key2=>$value2){
        if(preg_match($searchPhrase,$value2)){
            $matches[$x][$y]['key1']=$key;
            $matches[$x][$y]['key2']=$key2;
            $matches[$x][$y]['arr1']=$value;
            $matches[$x][$y]['arr2']=$value2;   
        }
        $y++;
    }
    unset($y);
    $x++;
}

print_r($matches);


?>

Output looks like this:

        Array
(
    [1] => Array
        (
            [0] => Array
                (
                    [key1] => 1
                    [key2] => 0
                    [arr1] => Hello
                    [arr2] => hello
                )

        )

    [2] => Array
        (
            [2] => Array
                (
                    [key1] => 2
                    [key2] => 2
                    [arr1] => World
                    [arr2] => World
                )

        )

    [3] => Array
        (
            [4] => Array
                (
                    [key1] => 3
                    [key2] => 4
                    [arr1] => Foo
                    [arr2] => foo
                )

        )

    [4] => Array
        (
            [5] => Array
                (
                    [key1] => 4
                    [key2] => 5
                    [arr1] => Bar1
                    [arr2] => BaR1
                )

        )

    [5] => Array
        (
            [5] => Array
                (
                    [key1] => 5
                    [key2] => 5
                    [arr1] => Bar
                    [arr2] => BaR1
                )

            [6] => Array
                (
                    [key1] => 5
                    [key2] => 6
                    [arr1] => Bar
                    [arr2] => Bar
                )

        )

)

Upvotes: 0

nickb
nickb

Reputation: 59699

This seemed to work for me, but I'm sure there are some edge cases I'm missing that you'd need to test for:

foreach( $arr1 as $i => $val1) {
    $result = null;
    // Search the second array for an exact match, if found
    if( ($found = array_search( $val1, $arr2, true)) !== false) {
            $result = $found; 
    } else {
        // Otherwise, see if we can find a case-insensitive matching string where  the element from $arr2 is at the 0th location in the one from $arr1
        foreach( $arr2 as $j => $val2) {            
            if( stripos( $val1, $val2) === 0) {
                $result = $j;
                break;
            }
        }
    }
    $arr3[$i] = $result;
}

It produces your desired output array:

Array ( [0] => 3 [1] => 0 [2] => 2 [3] => 4 [4] => 5 [5] => 6 )  

Upvotes: 1

Harry
Harry

Reputation: 4956

Looks like you need 2 foreach loops, and stripos (or mb_stripos for Unicode) for comparing.

Upvotes: 0

ax.
ax.

Reputation: 59927

Try array_uintersect() with a callback function that implements your "matching" algorithm.

Upvotes: 0

Related Questions