2017-05-15 74 views
7

想知道是否有更有效的方法来检测字符串是否包含使用正则表达式的一次或多次字母表中的每个字母?字符串中每个字母至少有一次?

我明白任何建议

$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; 
     } 
    } 
} 
+3

我投票关闭这一问题作为题外话,因为它是关于[codereview.se] – hjpotter92

+1

我不要求我的代码,代码工作回顾。我正在寻求一种使用正则表达式来实现这一点的方法。 – AnchovyLegend

+0

为什么使用正则表达式? – axiac

回答

3

用正则表达式,你可以做到这一点,但它不是最优也不会很快在所有,@hjpotter如果从很远的更快的方法:

var_dump(strlen(preg_replace('~[^a-z]|(.)(?=.*\1)~i', '', $str)) == 26); 

它会删除所有非字母字符,所有重复字母(不区分大小写),并比较26

  • [^a-z]匹配任何非字母字符
  • (.)捕获GRO字母串长度高达1
  • (?=.*\1)检查是否相同字母是其他地方(右侧)
  • 第i改性剂使图案不区分大小写
+0

谢谢你,你能解释的正则表达式模式是如何工作的,由左到右?:) – AnchovyLegend

0

您当前的程序将打印pangram具有26+字母,这意味着所有的字符串,甚至aaa...是全字母短句。

在你的内部循环,你可以打破如果来自a-z任何字符未发现:

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; 
    } 
} 

一个正则表达式是不是在这种情况下最优的。另一种方法是使用array_mapstr_count

+0

我很欣赏这种努力,但是这并不回答这个问题,然而你对代码的工作原理的第一个假设是错误的。 – AnchovyLegend

+0

@AnchovyLegend啊,我没有看到'break'那里! – hjpotter92

0

使布尔的阵列与长度26。然后可以循环通过你的字符串只有一次。在伪代码(因为我不知道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 

你需要弄清楚如何使字符索引到数组,但这不应该太难。

2

我没有任何正则表达式的答案。但没有正则表达式,你可以尝试使用PHP的count_chars函数。

例如:

$test_string = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz'; 
echo count(count_chars($test_string, 1)); 

给你26 - 这是从$有大于零的频率test_string独特的字符数。

+0

我喜欢这个解决方案,出色地完成。 – AnchovyLegend

5

只需使用array_diff

count(array_diff($az, $str)) > 0; 
相关问题