Recently I fell into a quite interesting problem.

Imagine that you want to send a mass email. You have two different set of arrays. One is your mailing list and the second is your filter email list. The final recipients will be the array_intersect of those 2 arrays. So far so good…

But what if the elements of the first array are also arrays? And what if you have stored values seperated by semicolon or any other character?

Lets split the problem into smaller ones.

We have the following arrays…

{% highlight php %} $array1 = array( array(’email’=>‘test@test.com;test2@test.com’,‘saluation’=>‘Test’, ‘value’=>‘some value’), array(’email’=>‘another.test@test.com’, ‘salutation’=>‘Another test’, ‘value’=>‘another value’), );

$array2 = array(
	array('email'=>'test@test.com'),
	array('email'=>'test2@test.com'),
);

{% endhighlight %}

What we want to achieve is an array containing the test@test.com and test2@test.com with the rest of the values.

A simple array_intersect will not do the job, it will return a notice and the $array1 as it is. We need a different approach.

First thing is to brake the element containing the semicolon into 2 different rows and copy their additional values.

{% highlight php %} $subset = array(); foreach ($multidimentionalArray as $key => $value) {

        $keys = array_keys($value);
        $keys = array_flip($keys);
		unset($keys[$filterKey]);
		$keys = array_flip($keys);

        if ( strpos($value[$filterKey], ';') !== false ) {

            $tmp = explode(';', $value[$filterKey]);

            foreach ($tmp as $tmpValue) {

                $subset[] = self::injectAdditionalFields($filterKey, $tmpValue, $keys, $value);
            }

        }else{

            $subset[] = self::injectAdditionalFields($filterKey, $value[$filterKey], $keys, $value);
    }

{% endhighlight %}

Where injectAdditionalFields is the following function.

{% highlight php %} private static function injectAdditionalFields($filterKey, $tmpValue, $keys, $value) { $tmpTable = array(); $tmpTable[$filterKey] = $tmpValue; foreach ($keys as $key) { $tmpTable[$key] = $value[$key]; }

    return $tmpTable;
}

{% endhighlight %}

filterKey is the key of the internal arrays that we want to compare. In our case it will be the email. We need to append the rest of the key=>values to the multiple rows, based on the semicolon explosion… $subset is our new array and the $tempTable is the seperation of the emails.

At this point the $subset table looks like this….

{% highlight php %} Array ( [0] => Array ( [email] => test@test.com [saluation] => Test [value] => some value )

[1] => Array
    (
        [email] => test2@test.com
        [saluation] => Test
        [value] => some value
    )

[2] => Array
    (
        [email] => another.test@test.com
        [salutation] => Another test
        [value] => another value
    )
)

{% endhighlight %}

For the final step I’ll use the array_uintersect with a custom callback function.

{% highlight php %} $results = array_uintersect($subset, $filterArray, ‘self::emailCompare’);

private static function emailCompare($val1, $val2) { return strcmp($val1[self::$filterKey], $val2[self::$filterKey]); } {% endhighlight %}

And the result is ….

{% highlight php %} Array ( [0] => Array ( [email] => test@test.com [saluation] => Test [value] => some value )

[1] => Array
    (
        [email] => test2@test.com
        [saluation] => Test
        [value] => some value
    )
)

{% endhighlight %}

There you go…the source code is on my github

I’m always open to suggestions and improvements!

Cheers, Argi