Was wondering if there was a more efficient way to detect if a string contains every letter in the alphabet one or more times using regex?
I appreciate any suggestions
$str = str_split(strtolower('We promptly judged antique ivory buckles for the next prize'));
$az = str_split('abcdefghijklmnopqrstuvwxyz');
$count = 0;
foreach($az as $alph) {
foreach($str as $z) {
if($alph == $z) {
$count++;
break;
}
}
}
With regex you can do that, but it isn’t optimal nor fast at all, @hjpotter way if from far faster:
var_dump(strlen(preg_replace('~[^a-z]|(.)(?=.*)~i', '', $str)) == 26);
It removes all non letter characters, all duplicate letters (case insensitive), and compares the string length with 26.
[^a-z]
matches any non letter character(.)
captures a letter in group 1(?=.*\1)
checks if the same letter is somewhere else (on the right)- the i modifier makes the pattern case insensitive
Answer:
Just use array_diff:
count(array_diff($az, $str)) > 0;
Answer:
I don’t have any regex answer. But without regex you can try using PHP’s count_chars function.
For example:
$test_string = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz';
echo count(count_chars($test_string, 1));
Gives you 26 – which is the number of unique chars from $test_string with a frequency greater than zero.
Answer:
You current program will print pangram
for all strings having 26+ alphabets, which means, even aaa...
is a pangram.
In your inner loop, you can just break if any character from a-z
is not found:
function is_pangram($str) {
if (strlen($str) < 26) return false;
$az = str_split('abcdefghijklmnopqrstuvwxyz');
for ($az as $char) {
if (stripos($str, $char) === false)
return false;
return true;
}
}
A regex is not optimal in this situation. An alternative approach would be using array_map
and str_count
.
Answer:
Make an array of Booleans with length 26. Then you can loop through your string just once. In pseudo code (because I don’t know PHP):
Boolean b[26]; // Initialized to false
count = 0;
Loop for each char c in string
if (not b[c]) then
++count;
b[c] = true
end
if (count == 26)
break; // All present;
end
end
// If count < 26 then not all present
You need to figure out how to make the character index into the array, but that shouldn’t be too hard.