I want to know if there is a way to compare by means of some PHP method, and verify that two chains regardless of the order are the same,
for example:
$string1 = "Pedro Perez";
$string2 = "Perez Pedro";
So my question is how can I make this TRUE
in a comparison. Clearly, your order makes it different.
I ask this question because I am developing a search, and I want a comparison of $string1
and $string2
to be taken as the same value, regardless of the order they have, as long as the string has the same words
You can try doing this.
In simple ways, here you go...
<?php
$string1 = "Pedro Perez";
$string2 = "Perez Pedro";
$string1 = explode(" ", $string1);
$string2 = explode(" ", $string2);
// Update: You don't save the output of sort, as it's by reference.
sort($string1);
sort($string2);
$string1 = implode(" ", $string1);
$string2 = implode(" ", $string2);
var_dump($string1 === $string2);
?>
You explode it by space and intersect both arrays as follows and check its count
$string1 = "Pedro Perez";
$string2 = "Perez Pedro";
$s1 = array_unique(explode(" ", $string1));
$s2 = array_unique(explode(" ", $string2));
$temp = array_intersect($s1, $s2);
var_dump(count($temp) == count($s1) && count($temp) == count($s2));
EDIT
For more than two words here is the snippet,
$string1 = "Perez Perez Pedro";
$string2 = "Perez Pedro Perez";
list($s1,$s2) = [explode(" ", $string1), explode(" ", $string2)];
sort($s1);sort($s2);
var_dump($s1 === $s2);
Working demo.
Yet another approach
$string1 = "Pedro Perez";
$string2 = "Perez Pedro";
$s1 = explode(" ", $string1);
$s2 = explode(" ", $string2);
$comp = empty( array_diff($s1, $s2) ) ? true : false;
The trivial part is to split the strings into words and compare the arrays by size. If the size is not the same, the strings can't be the same:
function str_equals_ignore_word_order(string $str1, string $str2): bool
{
$words1 = explode(' ', $str1);
$words2 = explode(' ', $str2);
if (count($words1) !== count($words2)) {
return false;
}
// Here comes one of the following or already suggested solutions.
}
With that established, we have quite a few of possible solutions for the actual comparison of two arrays of words, which are expected to be in different order.
Sort and compare (simplified without implode
):
sort($words1);
sort($words2);
return $words1 === $words2;
This is safe to do and will not change the input as strings are copied when they are passed to a function and we even copied the string into parts when using explode
.
Counting the occurences of each word and taking the word count into consideration prevents issues other solutions have with words that occur twice in the input strings. This solution also allows to select different comparisons of the dictionaries:
$words1 = array_count_values($words1);
$words2 = array_count_values($words2);
// Comparison 1
$intersect = array_intersect_assoc($words1, $words2);
return count($intersect) === count($words1) && count($words1) === count($words2);
// Comparison 2
$diff = array_diff_assoc($words1, $words2);
return empty($diff);
If it's expected that the input contains spelling errors like two spaces right after another ' '
, you should use array_filter($words1)
on both word arrays to ensure that no NULL
words are matched.
A short function for the fun of it, that doesn't sort if necessary.
// Split the sentences, compare word count, sort words, compare sorted words
function compare_words($a, $b) {
return count($a = explode(' ', $a)) == count($b = explode(' ', $b))
&& sort($a)
&& sort($b)
&& $a === $b;
};