Wikipedia定义了许多人们可以使用的表情符号。我想将此列表与字符串中的单词匹配。我现在有这个:
$string = "Lorem ipsum :-) dolor :-| samet";
$emoticons = array(
'[HAPPY]' => array(' :-) ', ' :) ', ' :o) '), //etc...
'[SAD]' => array(' :-( ', ' :( ', ' :-| ')
);
foreach ($emoticons as $emotion => $icons) {
$string = str_replace($icons, " $emotion ", $string);
}
echo $string;
输出:
Lorem ipsum [HAPPY] dolor [SAD] samet
原则上这是有效的。但是,我有两个问题:
正如您所看到的,我在数组中的每个表情符号周围放置空格,例如':-)'而不是':-)'这使得数组在我看来不太可读。有没有办法存储没有空格的表情符号,但仍然匹配$ string,周围有空格? (和现在的代码一样有效吗?)
或者有没有办法将表情符号放在一个变量中,然后在空格上爆炸以检查$ string?像
这样的东西$ emoticons = array( '[HAPPY]'=> “>:] :-) :):o):]:3:c):> =] 8)=):}:^)”, '[SAD]'=> “:' - (:'(:' - ):')”//等......
str_replace是最有效的方法吗?
我问,因为我需要检查数百万字符串,所以我正在寻找最有效的方法来节省处理时间:)
答案 0 :(得分:4)
这是使用CPAN的Perl第三方Regexp::Assemble模块的想法。例如,鉴于此计划:
#!/usr/bin/env perl
use utf8;
use strict;
use warnings;
use Regexp::Assemble;
my %faces = (
HAPPY => [qw¡ :-) :) :o) :-} ;-} :-> ;-} ¡],
SAD => [qw¡ :-( :( :-| ;-) ;-( ;-< |-{ ¡],
);
for my $name (sort keys %faces) {
my $ra = Regexp::Assemble->new();
for my $face (@{ $faces{$name} }) {
$ra->add(quotemeta($face));
}
printf "%-12s => %s\n", "[$name]", $ra->re;
}
它将输出:
[HAPPY] => (?-xism:(?::(?:-(?:[)>]|\})|o?\))|;-\}))
[SAD] => (?-xism:(?::(?:-(?:\||\()|\()|;-[()<]|\|-\{))
你真的不需要那些额外的东西,所以那些会减少到:
[HAPPY] => (?:-(?:[)>]|\})|o?\))|;-\}
[SAD] => (?:-(?:\||\()|\()|;-[()<]|\|-\{
左右。您可以将其构建到Perl程序中以修剪额外的位。然后,您可以将右侧直接放入preg_replace
。
我执行use utf8
的原因是因为我可以使用¡
作为我的qw//
分隔符,因为我不想弄乱那里的转义内容。
如果整个程序都在Perl中,你就不需要这样做了,因为Perl的现代版本已经知道会自动为你做这件事。但是知道如何使用模块仍然很有用,这样你就可以生成在其他语言中使用的模式。
答案 1 :(得分:3)
这听起来像是正则表达式的一个很好的应用程序,它是模糊文本匹配和替换的工具。 str_replace
是完全文本搜索和替换的工具;正则表达式将允许您搜索整个类“看起来像 this ”的文本,其中 this 是根据您将接受的字符类型,有多少来定义的他们,以什么顺序等等。
如果您使用正则表达式,那么......
\s
通配符将匹配空格,因此您可以匹配\s$emotion\s
。
(还要考虑表情符号出现在字符串末尾的情况 - 即that was funny lol :)
- 您不能总是假设表情符号周围会有空格。您可以编写一个处理此表情符号的正则表达式。)< / p>
您可以编写一个匹配列表中任何表情符号的正则表达式。您可以使用替换符号|
执行此操作,您可以将其视为OR
符号。语法为(a|b|c)
以匹配模式a
或b
或c
。
例如,(:\)|:-\)|:o\))
将与:),:-),:o)
中的任何一个匹配。请注意,我必须转义)
,因为它们在regexp中具有特殊含义(括号用作分组运算符。)
过早优化是万恶之源。
首先尝试最明显的事情。如果这不起作用,您可以稍后对其进行优化(在您对代码进行分析之后,确保这确实会给您带来切实的性能优势。)
如果您想学习正则表达式,请尝试TextWrangler manual的第8章。这是对正则表达式的用法和语法的非常容易理解的介绍。
注意:我的建议是独立于编程语言。我的PHP-fu比我的Python-fu弱得多,所以我无法提供示例代码。 :(
答案 2 :(得分:2)
我会先使用str_replace
和那些带空格的数组开始尝试最简单的实现。如果表现不可接受,请为每种情绪尝试一个正则表达式。这压缩了很多东西:
$emoticons = array(
'[HAPPY]' => ' [:=]-?[\)\]] ',
'[SAD]' => ' [:=]-?[\(\[\|] '
);
如果性能仍然不可接受,你可以使用更高级的东西,比如后缀树(参见:http://en.wikipedia.org/wiki/Suffix_tree),它允许你只扫描所有表情符号的字符串一次。这个概念很简单,你有一个树,它的根是一个空格(因为你想在表情符号之前匹配一个空格),第一个孩子是':'和'=',那么':'的孩子是']', ')',' - '等。你有一个循环扫描字符串,char由char。当你找到一个空格时,你移动到树中的下一个级别,然后查看下一个字符是否是该级别的节点之一(':'或'='),如果是,则移动到下一个级别,等等如果在任何时候,当前char不是当前级别的节点,则返回root。
答案 3 :(得分:2)
简介评论:请一次只提出一个问题。你会得到更好的答案。接下来,如果您没有向我们展示您迄今为止所做的指标,则无法获得良好的性能建议。
从我的代码中我可以看到,你做两次字符串处理可以保存,将替换放入特定的空格中。您可以先使用您的定义将其展开:
$emoticons = array(
' [HAPPY] ' => array(' :-) ', ' :) ', ' :o) '), //etc...
' [SAD] ' => array(' :-( ', ' :( ', ' :-| ')
);
foreach ($emoticons as $replace => $search)
{
$string = str_replace($search, $replace, $string);
}
每次拨打电话时,这样可以节省一些微秒,这样可以提供更好的性能,您可能不会注意到。这让我想到你应该用C编写它并编译它。
更靠近C将使用编译一次然后重新使用的正则表达式,这已在另一个答案中提出。这样做的好处是,如果您多次运行相同的表达式和,您可以使用PHP以最快的方式执行此操作,您可以预先生成正则表达式,因此您可以将其存储为您可以更轻松地进行编辑。然后,您可以缓存正则表达式,以防您甚至需要调整性能几乎没有。
1。正如你所看到的,我在数组中的每个表情符号周围放置空格,例如':-)'而不是':-)'这使得数组在我看来不太可读。有没有办法存储没有空格的表情符号,但仍然匹配$ string,周围有空格? (和代码现在一样有效吗?)
是的,这是可能的,但不是更有效,因为您需要将配置数据进一步处理为替换数据。不知道你真正谈论哪种效率,但我假设后者,所以答案是,可能但不适合你的特殊用例。通常情况下,我更喜欢更容易编辑的东西,所以说你处理它的效率更高,而不是关心处理速度,因为通过在多台计算机上分配处理可以很好地缩短处理速度。
2。或者是否有一种方法可以将表情符号放在一个变量中,并在空间上爆炸以检查$ string?像
这样的东西
$emoticons = array( '[HAPPY]' => ">:] :-) :) :o) :] :3 :c) :> =] 8) =) :} :^)", '[SAD]' => ":'-( :'( :'-) :')" //etc...
当然,这是可能的,但你会遇到与1相同的问题。
3。 str_replace是最有效的方法吗?
现在使用您提供的代码,这是您询问的唯一方式。由于你没有别的选择告诉我们,它至少为你工作,在这个时间点,这是最有效的方式。所以现在,是的。
答案 4 :(得分:2)
如果您想要替换表情符号的$ string是由您网站的访问者提供的(我的意思是用户的输入,如评论或其他内容),那么您不应该传达之前或之后会有空格表情符号。还有至少几个表情符号,它们非常相似但不同,如:-)和:-))。 所以如果你定义你的表情符号数组,我认为你将获得更好的结果:
$emoticons = array(
':-)' => '[HAPPY]',
':)' => '[HAPPY]',
':o)' => '[HAPPY]',
':-(' => '[SAD]',
':(' => '[SAD]',
...
)
当你填写所有的查找/替换定义时,你应该以某种方式重新排序这个数组,没有机会用:-)取代:-))。我相信如果按长度排序数组值就足够了。这是为了你打算使用str_replace()。 strtr()会自动按长度排序!
如果您担心性能问题,可以查看strtr vs str_replace,但我建议您进行自己的测试(关于$ string长度和查找/替换定义,您可能得到不同的结果)。
最简单的方法是,如果“查找定义”不包含尾随空格:
$string = strtr( $string, $emoticons );
$emoticons = str_replace( '][', '', trim( join( array_unique( $emoticons ) ), '[]' ) );
$string = preg_replace( '/\s*\[(' . join( '|', $emoticons ) . ')\]\s*/', '[$1]', $string ); // striping white spaces around word-styled emoticons