Php 评估字符串是否为英文:最佳和最简单的实践?

Php 评估字符串是否为英文:最佳和最简单的实践?,php,string,Php,String,我有足够长的字符串(5000+字符),我需要检查它是否是英文的 经过简短的网络搜索,我找到了几种解决方案: 使用(它看起来很吸引人,但我仍在避免使用我不了解其工作原理的解决方案) 检查(我在下面做了一个带有一些注释的函数) 检查字符串中是否有国家字符(如č、ß等) 检查字符串中是否有“is”、“the”等标记 因此,函数如下所示: function is_english($str){ // Most used English chars frequencies $chars

我有足够长的字符串(5000+字符),我需要检查它是否是英文的

经过简短的网络搜索,我找到了几种解决方案:

  • 使用(它看起来很吸引人,但我仍在避免使用我不了解其工作原理的解决方案)
  • 检查(我在下面做了一个带有一些注释的函数)
  • 检查字符串中是否有国家字符(如č、ß等)
  • 检查字符串中是否有“is”、“the”等标记
因此,函数如下所示:

function is_english($str){
    // Most used English chars frequencies
    $chars = array(
        array('e',12.702),
        array('t', 9.056),
        array('a', 8.167),
        array('o', 7.507),
        array('i', 6.966),
        array('n', 6.749),
        array('s', 6.327),
        array('h', 6.094),
        array('r', 5.987),
    );

    $str = strtolower($str);
    $sum = 0;
    foreach($chars as $key=>$char){
        $i = substr_count($str,$char[0]);
        $i = 100*$i/strlen($str);    // Normalization
        $i = $i/$char[1];
        $sum += $i;
    }
    $avg = $sum/count($chars);

    // Calculation of mean square value
    $value = 0;
    foreach($chars as $char)
        $value += pow($char[2]-$avg,2);

    // Average value
    $value = $value / count($chars);
    return $value;
}
通常,该函数估计字符频率,并将其与给定模式进行比较。当频率接近模式时,结果应接近0

不幸的是,它的效果不太好:主要是我认为结果0.05和更低是英语,而不是更高。但是有许多英文字符串的值很高,而许多外国字符串(在我的例子中,大部分是德语)的值很低

我还无法实施第三个解决方案,因为我无法找到任何全面的字符集-外语标记

forth看起来很吸引人,但我想不出哪个标记最适合使用

有什么想法吗


PS经过一番讨论后,佐德提出这个问题与这个问题是重复的,这个问题只回答了一部分。所以我想保持这个问题的独立性。

这个问题被称为语言检测,用一个函数就可以解决。我建议您使用github。

我认为第四种解决方案可能是您最好的选择,但我会扩展它,以包括更广泛的词典

您可以在以下网址找到一些全面的列表:

在当前的实现中,您将遇到一些挫折,因为许多语言使用标准拉丁字母表。甚至超出标准拉丁字母表的语言也可以说主要使用“符合英语标准的字符”。例如,句子“Ich bin lustig”是德语,但只使用拉丁字母字符。同样,“Jeg er Glay”是丹麦语,但只使用拉丁字母。当然,在5000多个字符的字符串中,您可能会看到一些非拉丁字符,但这并不能保证。此外,仅关注字符频率,您可能会发现使用拉丁字母的外国语言通常具有相似的字符出现频率,从而使现有解决方案无效

通过使用英语词典查找出现的英语单词,您将能够查看字符串并准确确定其中有多少单词是英语单词,然后从中计算出英语单词数量的频率。(较高的百分比表明该句子可能是英语。)

以下是一个潜在的解决方案:

<?php
$testString = "Some long string of text that you would like to test.";

// Words from: https://en.wikipedia.org/wiki/Most_common_words_in_English
$common_english_words = array('time', 'person', 'year', 'way', 'day', 'thing', 'man', 'world', 'life', 'hand', 'part', 'child', 'eye', 'woman', 'place', 'work', 'week', 'case', 'point', 'government', 'company', 'number', 'group', 'problem', 'fact', 'be', 'have', 'do', 'say', 'get', 'make', 'go', 'know', 'take', 'see', 'come', 'think', 'look', 'want', 'give', 'use', 'find', 'tell', 'ask', 'seem', 'feel', 'try', 'leave', 'call', 'good', 'new', 'first', 'last', 'long', 'great', 'little', 'own', 'other', 'old', 'right', 'big', 'high', 'different', 'small', 'large', 'next', 'early', 'young', 'important', 'few', 'public', 'bad', 'same', 'able', 'to', 'of', 'in', 'for', 'on', 'with', 'at', 'by', 'from', 'up', 'about', 'into', 'over', 'after', 'beneath', 'under', 'above', 'the', 'and', 'a', 'that', 'i', 'it', 'not', 'he', 'as', 'you', 'this', 'but', 'his', 'they', 'her', 'she', 'or', 'an', 'will', 'my', 'one', 'all', 'would', 'there', 'their', 'I', 'we', 'what', 'so', 'out', 'if', 'who', 'which', 'me', 'when', 'can', 'like', 'no', 'just', 'him', 'people', 'your', 'some', 'could', 'them', 'than', 'then', 'now', 'only', 'its', 'also', 'back', 'two', 'how', 'our', 'well', 'even', 'because', 'any', 'these', 'most', 'us');

/* you might also consider replacing "'s" with ' ', because 's is common in English
   as a contraction and simply removing the single quote could throw off the frequency. */
$transformedTest = preg_replace('@\s+@', ' ', preg_replace("@[^a-zA-Z'\s]@", ' ', strtolower($testString)));

$splitTest = explode(' ', $transformedTest);

$matchCount = 0;
for($i=0;$i<count($splitTest);$i++){
    if(in_array($splitTest[$i], $common_english_words))
        $matchCount++;
}

echo "raw count: $matchCount\n<br>\nPercent: " . ($matchCount/count($common_english_words))*100 . "%\n<br>\n";
if(($matchCount/count($common_english_words)) > 0.5){
    echo "More than half of the test string is English. Text is likely English.";
}else{
    echo "Text is likely a foreign language.";
}
?>

我会选择第四种解决方案,并尝试搜索非英语。例如,如果你发现“the”,那么英语的可能性很高。如果你找到“el”或“la”,那么西班牙语的可能性就很高。我会搜索“der”、“die”和“das”,然后很有可能是德语。

我想在这种情况下,您要做的是尝试猜测字符串所用的语言,如果英语得分最高,则假设它是英语。如果你90%肯定是德语,那么80%肯定是英语是不好的。明白吗?为什么不能使用a-z的正则表达式检查?@user3137702,对不起,我不明白:(@zod)许多语言的字母表中都有a-z,这可能是“谢谢你的想法”的重复。关于非英语拉丁语字符串的频率:如果你查看我的问题链接到的维基百科页面,即使是拉丁语字符,频率也非常不同。所以我认为这种方法应该适用于长字符串。但我可以在计算中出错,或者字符串应该被清除。实际上我不知道。@VladaKatlinskaya,很有意思。我没有读过你链接到的维基百科文章,但我认为某些语言的频率可能类似。谢谢你指出这一点。我将立即为这一问题添加一个解决方案。看起来令人印象深刻。但是1G的内存我讨厌你的用法和需要学习的东西。