【问题标题】:Get the most used words with special characters获取带有特殊字符的最常用词
【发布时间】:2016-09-24 11:36:24
【问题描述】:

我想从数组中获取最常用的单词。唯一的问题是瑞典语字符(Å、Ä 和 Ö)只会显示为 �。

$string = 'This is just a test post with the Swedish characters Å, Ä, and Ö. Also as lower cased characters: å, ä, and ö.';
echo '<pre>';
print_r(array_count_values(str_word_count($string, 1, 'àáãâçêéíîóõôúÀÁÃÂÇÊÉÍÎÓÕÔÚ')));
echo '</pre>';

该代码将输出以下内容:

Array
(
    [This] => 1
    [is] => 1
    [just] => 1
    [a] => 1
    [test] => 1
    [post] => 1
    [with] => 1
    [the] => 1
    [Swedish] => 1
    [characters] => 2
    [�] => 1
    [�] => 1
    [and] => 2
    [�] => 1
    [Also] => 1
    [as] => 1
    [lower] => 1
    [cased] => 1
    [�] => 1
    [�] => 1
    [�] => 1
)

我怎样才能让它“看到”瑞典语字符和其他特殊字符?

【问题讨论】:

  • 您不应该对任何名称以str 开头的 PHP 函数不是多字节安全感到惊讶。手册中的用户 cmets 提出了替代方案。
  • @CBroe ...PHP function with a name starting with str...这个函数在哪里?
  • 试试这个函数mb_str_word_count而不是str_word_count:stackoverflow.com/a/17725577/6797531
  • @CatalinB 谢谢,但输出将是这样的:Array([This is just a test post with the Swedish characters �, �, and Ö. Also as lower cased characters: �, �, and �.] =&gt; 1)

标签: php arrays count words


【解决方案1】:

所有这些都是在您使用 UTF-8 的假设下运行的。

您可以使用preg_split() 采取一种简单的方法,在任何分隔符、标点符号或控制字符上拆分您的字符串。

preg_split 例子:

$split = preg_split('/[\pZ\pP\pC]/u', $string, -1, PREG_SPLIT_NO_EMPTY);
print_r(array_count_values($split));

输出:

Array
(
    [This] => 1
    [is] => 1
    [just] => 1
    [a] => 1
    [test] => 1
    [post] => 1
    [with] => 1
    [the] => 1
    [Swedish] => 1
    [characters] => 2
    [Å] => 1
    [Ä] => 1
    [and] => 2
    [Ö] => 1
    [Also] => 1
    [as] => 1
    [lower] => 1
    [cased] => 1
    [å] => 1
    [ä] => 1
    [ö] => 1
)

这适用于您给定的字符串,但不一定以区域设置感知的方式拆分单词。例如,诸如“isn't”之类的缩写会被分解为“isn”和“t”。


谢天谢地,Intl extension 在 PHP 7 中添加了大量功能来处理此类事情。

计划是:

(*请注意,无论您使用什么方法来分解字符串,您都可能希望执行规范化 - 在上面的 preg_split 或您决定使用的任何方法之前执行此操作都是合适的.)

国际示例:

$string = Normalizer::normalize($string);

$iter = IntlBreakIterator::createWordInstance("sv_SE");
$iter->setText($string);
$words = $iter->getPartsIterator();

$split = [];
foreach ($words as $word) {
    // skip text fragments consisting only of a space or punctuation character
    if (IntlChar::isspace($word) || IntlChar::ispunct($word)) {
        continue;
    }
    $split[] = $word;
}

print_r(array_count_values($split));

输出:

Array
(
    [This] => 1
    [is] => 1
    [just] => 1
    [a] => 1
    [test] => 1
    [post] => 1
    [with] => 1
    [the] => 1
    [Swedish] => 1
    [characters] => 2
    [Å] => 1
    [Ä] => 1
    [and] => 2
    [Ö] => 1
    [Also] => 1
    [as] => 1
    [lower] => 1
    [cased] => 1
    [å] => 1
    [ä] => 1
    [ö] => 1
)

这更冗长,但如果您希望 ICU(支持 Intl 扩展的库)在理解单词的组成部分时承担繁重的工作,这可能是值得的。

【讨论】:

  • 非常感谢您提供非常详细的回答。你的回答和 MarZab 的回答都很好。您的正则表达式将接受笑脸,而 MarZab 的正则表达式不会。如果可以的话,我会接受这两个答案,但由于 MarZab 的正则表达式不接受笑脸,我会接受他的答案。
【解决方案2】:

这是一个使用 Unicode 标点符号来拆分“单词”的正则表达式解决方案,然后只是一个常规数组出现计数。

array_count_values(preg_split('/[[:punct:]\s]+/u', $string, -1, PREG_SPLIT_NO_EMPTY));

生产:

Array
(
    [This] => 1
    [is] => 1
    [just] => 1
    [a] => 1
    [test] => 1
    [post] => 1
    [with] => 1
    [the] => 1
    [Swedish] => 1
    [characters] => 2
    [Å] => 1
    [Ä] => 1
    [and] => 2
    [Ö] => 1
    [Also] => 1
    [as] => 1
    [lower] => 1
    [cased] => 1
    [å] => 1
    [ä] => 1
    [ö] => 1
)

这是在 unicode 控制台中测试的,如果您使用的是浏览器,您可能需要使用编码。在浏览器中创建&lt;meta&gt; 标签或设置编码,或发送 PHP 标头。

【讨论】:

    【解决方案3】:

    我设法通过将 ÅåÄäÖö 添加到 àáãâçêéíîóõôúÀÁÃÂÇÊÉÍÎÓÕÔÚ 中删除了 � 符号。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-30
      • 2011-07-29
      • 2012-11-24
      • 1970-01-01
      • 1970-01-01
      • 2020-02-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多