【问题标题】:Performance improvement in text preprocessing文本预处理的性能提升
【发布时间】:2012-11-02 12:33:08
【问题描述】:

有没有办法改进此代码并维护功能?其中一些是在 Windows 和 Linux 上检查代码和输出的结果,因此需要“多操作系统”。

// Remove tags
$input = strip_tags($input);
// Converts accented to non-accented
$input =  iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $input);
// String to lower
$input = strtolower($input);
// Remove all non-word and non-space chars
$input = preg_replace('/[^\sa-z]/', '', $input);
// Replace enters
$input = preg_replace('/[\r\n]/', ' ', $input);
// Remove stopwords
$input = preg_replace('/\b(' . implode('|', $stopwords) . ')\b/', '', $input);
// Remove individual chars
$input = preg_replace('/\b([a-z])\b/', '', $input);
// Trim it
$input = trim($input);
// Remove multiple spaces
$input = preg_replace("/[[:blank:]]+/", " ", $input);

输入:

<doc id="603" url="http://it.wikipedia.org/wiki/Esperanto">
Esperanto.
Esperanto (pôvodne Lingvo Internacia – „medzinárodný jazyk“) je najrozšírenejší <a     href="Medzin%C3%A1rodn%C3%BD_pomocn%C3%BD_jazyk">medzinárodný</a> <a     href="Umel%C3%BD_jazyk">plánový jazyk</a>. Názov je odvodený od <a     href="Pseudonym">pseudonym</a>u, pod ktorým v roku <a href="1887">1887</a> zverejnil lekár     <a href="Ludwik_Lejzer_Zamenhof">L. L. Zamenhof</a> základy tohto jazyka. Zámerom tvorcu     bolo vytvoriť ľahko naučiteľný a použiteľný neutrálny jazyk, vhodný na použitie v     medzinárodnej komunikácii. Cieľom nebolo nahradiť <a href="N%C3%A1rodn%C3%BD_jazyk">národné     jazyky</a>, čo bolo neskôr aj deklarované v <a     href="Boulonsk%C3%A1_deklar%C3%A1cia">Boulonskej deklarácii</a>.
Hoci žiaden <a href="%C5%A1t%C3%A1t">štát</a> neprijal esperanto ako <a href="%C3%BAradn%C3%BD_jazyk">úradný jazyk</a>, používa ho komunita s odhadovaným počtom hovoriacich 100 000 až 2 000 000, z čoho približne 1 000 tvoria rodení hovoriaci. Získalo aj isté medzinárodné uznania, napríklad dve rezolúcie <a href="UNESCO">UNESCO</a> či podporu známych osobností verejného života. V súčasnosti sa esperanto využíva pri <a href="Cestovanie">cestovaní</a>, dopisovaní, medzinárodných stretnutiach a kultúrnych výmenách, <a href="Kongres">kongres</a>och, <a href="Veda">vedeckých</a> diskusiách, v pôvodnej aj prekladovej
</doc>

输出:

世界语世界语povodne国际语medzinarodny jazyk najrozsirenejsi medzinarodny planovy jazyk nazov odvodeny pseudonymu ktorym Roku公司zverejnil礼加柴门霍夫ZAKLADY东都jazyka zamerom tvorcu vytvorit lahko naucitelny pouzitelny neutralny jazyk vhodny pouzitie medzinarodnej komunikacii cielom nebolo nahradit narodne jazyky neskor deklarovane boulonskej deklaracii HOCI ziaden STAT neprijal世界语uradny jazyk pouziva komunita odhadovanym poctom hovoriacich银鲑priblizne tvoria rodeni hovoriaci ziskalo ISTE medzinarodne uznania napriklad DVE rezolucie UNESCO podporu znamych osobnosti verejneho zivota sucasnosti世界语vyuziva cestovani dopisovani medzinarodnych stretnutiach kulturnych vymenach kongresoch vedeckych diskusiach povodnej prekladovej

【问题讨论】:

    标签: php regex linux windows text-processing


    【解决方案1】:

    您确定这是您应用程序的瓶颈吗?在进行没有的性能优化之前,您绝对应该对其进行分析。

    我不确定这是否会显着提高性能,但至少它会稍微简化代码。您可以通过将它们折叠到 Replace enters 调用中来摆脱最后两个语句:

    // Replace all (consecutive) whitespace characters with a single space:
    $input = preg_replace('/\s+/', ' ', $input);
    

    然后你可以将这两个替换组合起来:

    // Remove all stopwords and single letters:
    $input = preg_replace('/\b(' . implode('|', $stopwords) . '|[a-z])\b/', '', $input);
    

    所以你最终得到了这个:

    // Remove tags
    $input = strip_tags($input);
    // Converts accented to non-accented
    $input =  iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $input);
    // String to lower
    $input = strtolower($input);
    // Remove all non-word and non-space chars
    $input = preg_replace('/[^\sa-z]/', '', $input);
    // Replace all (consecutive) whitespace characters with a single space:
    $input = preg_replace('/\s+/', ' ', $input);
    // Remove all stopwords and single letters:
    $input = preg_replace('/\b(' . implode('|', $stopwords) . '|[a-z])\b/', '', $input);
    // Trim it
    $input = trim($input);
    

    事实上,您可以在最后一个 preg_replace 中再添加两个替代方案来使用 trim,但我发现这相当模糊,而且我不知道这是否对您的表现有好处。

    【讨论】:

    • 这不是瓶颈,但是当我尝试使用各种函数时,str_replace 非常慢,例如停用词,我想知道是否有一些更有效的方法来编写发布的代码。这段代码我只在 110MB 的文本上运行一次,但需要 186 792 毫秒。不多,这些改进只是为了获得编写有效代码的经验。
    【解决方案2】:

    m.buettner 的回答是一个好的开始。使用该解决方案,我的基准测试显示速度提高了 25% 以上。

    PCRE 'S'“研究”修饰符

    对于某些正则表达式,PCRE 'S' 学习修饰符可以大大加快匹配速度。以下是 m.buettner 代码的增强版:

    // Remove tags
    $input = strip_tags($input);
    // Converts accented to non-accented
    $input =  iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $input);
    // String to lower
    $input = strtolower($input);
    // Remove all non-word and non-space chars
    $input = preg_replace('/[^\sa-z]+/S', '', $input);
    // Replace all (consecutive) whitespace characters with a single space:
    $input = preg_replace('/\s+/S', ' ', $input);
    // Remove all stopwords and single letters:
    $input = preg_replace('/\b('.implode('|', $stopwords).'|[a-z])\b/', '', $input);
    // Trim it
    $input = trim($input);
    

    这进一步改进了它,比原来的速度提高了大约 45%。请注意,S Study 修饰符对以文字或锚点开头的正则表达式没有帮助。瓶颈可能在$stopwords 语句中,具体取决于您在其中的数量。 (我使用了一个包含四个元素的简单数组进行基准测试:['one','two','three','four'])。更大的$stopwords 数组将显示更少的改进。

    在经典中还有更多有用的效率花絮:Mastering Regular Expressions (3rd Edition) - 必须阅读每个定期使用正则表达式的人。

    8^)

    【讨论】:

    • 我在停用词数组中使用了大约 200 个单词。通过上面的修改,我只有 8% 的改进,单词之间的空格有时不止一个。
    • 现在我将替​​换空白行替换为删除停用词行,输出就像我需要的一样,改进也约为 8%。但无论如何,它是一些东西。我浏览了 434 个文件并删除了大约 200 个停用词。
    【解决方案3】:

    看看以下内容:

    http://stuffivelearned.org/doku.php?id=programming:general:phpvspythonvsperl

    它比较了 PHP、Perl 和 Python 的正则表达式的速度。尤其要注意 Perl 的惊人速度,它只需要 PHP 所需时间的 20% 左右。

    【讨论】:

      猜你喜欢
      • 2011-08-07
      • 2013-04-21
      • 2015-12-07
      • 1970-01-01
      • 2014-08-05
      • 2013-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多