最近经常要对字符串进行匹配和替换操作,之前一般使用str_replace或者preg_replace,据说strtr的效率不错,所以对比了一下:
复制代码 代码如下:
$i = 0;
$t = microtime(true);
for(;$i<1000;$i++)
{
$str = strtr(md5($i), $p2);
}
var_dump(microtime(true)-$t); //0.085476875305176
$t = microtime(true);
for(;$i<2000;$i++)
{
$str = preg_replace($p, '', md5($i));
}
var_dump(microtime(true)-$t); //0.09863805770874
结果显示,strtr的效率比preg_replace高约15%左右。
趁着周末,查看了strtr的php源码:
复制代码 代码如下:
PHP_FUNCTION(strtr)
{
zval **str, **from, **to;
int ac = ZEND_NUM_ARGS();
//参数检查(zend_get_parameters_ex函数定义在zend_api.c文件中)
if (ac < 2 || ac > 3 || zend_get_parameters_ex(ac, &str, &from, &to) == FAILURE) {
WRONG_PARAM_COUNT;
}
//参数检查
if (ac == 2 && Z_TYPE_PP(from) != IS_ARRAY) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The second argument is not an array.");
RETURN_FALSE;
}
convert_to_string_ex(str);
/* shortcut for empty string */
//宏Z_STRLEN_PP定义在zend_operators.h
if (Z_STRLEN_PP(str) == 0) {
RETURN_EMPTY_STRING();
}
if (ac == 2) {
php_strtr_array(return_value, Z_STRVAL_PP(str), Z_STRLEN_PP(str), HASH_OF(*from));
} else {
convert_to_string_ex(from);
convert_to_string_ex(to);
ZVAL_STRINGL(return_value, Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);
php_strtr(Z_STRVAL_P(return_value),
Z_STRLEN_P(return_value),
Z_STRVAL_PP(from),
Z_STRVAL_PP(to),
MIN(Z_STRLEN_PP(from),
Z_STRLEN_PP(to)));
}
}
先看看php_strtr函数:
复制代码 代码如下:
//trlen是字符串str_from与str_to的长度的最小值
PHPAPI char *php_strtr(char *str, int len, char *str_from, char *str_to, int trlen)
{
int i;
unsigned char xlat[256]; //
if ((trlen < 1) || (len < 1)) {
return str;
}
//xlat的下标与值相等
for (i = 0; i < 256; xlat[i] = i, i++);
//把from到to字符串的每一个字符对应起来。例如:from="ab",to="cd",则会产生这样的对应'a'=>'c', 'b'=>'d'。
for (i = 0; i < trlen; i++) {
xlat[(unsigned char) str_from[i]] = str_to[i];
}
//替换(不过觉得这个函数的效率还有可以改进的地方,因为如果需要替换的字符只是占整个字符串很少的部分,这样就有大部分的赋值操作其实并没有什么意义,这样的情况下感觉先判断再赋值感觉会高效一点。有空测试一下)
for (i = 0; i < len; i++) {
str[i] = xlat[(unsigned char) str[i]];
}
return str;
}
可见,在处理strtr('abcdaaabcd', 'ab', 'efd')这样的操作时,应该是很高效的。
(注意:这个操作输出efcdeeefcd)
再看看php_strtr_array:
复制代码 代码如下:
static void php_strtr_array(zval *return_value, char *str, int slen, HashTable *hash)
{
zval **entry;
char *string_key;
uint string_key_len;
zval **trans;
zval ctmp;
ulong num_key;
int minlen = 128*1024;
int maxlen = 0, pos, len, found;
char *key;
HashPosition hpos;
smart_str result = {0};
HashTable tmp_hash;
//把替换数组从hash复制到tmp_hash,并记录下标字符串的最大和最小长度
zend_hash_init(&tmp_hash, 0, NULL, NULL, 0);
zend_hash_internal_pointer_reset_ex(hash, &hpos);
while (zend_hash_get_current_data_ex(hash, (void **)&entry, &hpos) == SUCCESS) {
switch (zend_hash_get_current_key_ex(hash, &string_key, &string_key_len, &num_key, 0, &hpos)) {
case HASH_KEY_IS_STRING:
len = string_key_len-1;
if (len < 1) {
zend_hash_destroy(&tmp_hash);
RETURN_FALSE;
}
zend_hash_add(&tmp_hash, string_key, string_key_len, entry, sizeof(zval*), NULL);
if (len > maxlen) {
maxlen = len;
}
if (len < minlen) {
minlen = len;
}
break;
//下标如果是整形的话会转换成字符串类型,例如:array(10=>'aa')转换成array('10'=>'aa')
case HASH_KEY_IS_LONG:
Z_TYPE(ctmp) = IS_LONG;
Z_LVAL(ctmp) = num_key;
convert_to_string(&ctmp);
len = Z_STRLEN(ctmp);
zend_hash_add(&tmp_hash, Z_STRVAL(ctmp), len+1, entry, sizeof(zval*), NULL);
zval_dtor(&ctmp);
if (len > maxlen) {
maxlen = len;
}
if (len < minlen) {
minlen = len;
}
break;
}
zend_hash_move_forward_ex(hash, &hpos);
}
key = emalloc(maxlen+1);
pos = 0;
//从字符串的第一个字符开始循环匹配,pos记录当前查找的位置
while (pos < slen) {
//当前位置加上最大长度,如果大于字符串长度,则最大长度就需要改变
if ((pos + maxlen) > slen) {
maxlen = slen - pos;
}
found = 0;
memcpy(key, str+pos, maxlen);
//从最大长度开始匹配,就是说对'abcd',若array('a'=>'e','ab'=>'f'),则会先把ab替换为f,而不是先把a换成e。
for (len = maxlen; len >= minlen; len--) {
key[len] = 0;
//因为使用了hash表,所以这样的效率还是挺高的
if (zend_hash_find(&tmp_hash, key, len+1, (void**)&trans) == SUCCESS) {
char *tval;
int tlen;
zval tmp;
if (Z_TYPE_PP(trans) != IS_STRING) {
tmp = **trans;
zval_copy_ctor(&tmp);
convert_to_string(&tmp);
tval = Z_STRVAL(tmp);
tlen = Z_STRLEN(tmp);
} else {
tval = Z_STRVAL_PP(trans);
tlen = Z_STRLEN_PP(trans);
}
//加入结果
smart_str_appendl(&result, tval, tlen);
//向前跳跃
pos += len;
found = 1;
if (Z_TYPE_PP(trans) != IS_STRING) {
zval_dtor(&tmp);
}
break;
}
}
if (! found) {
smart_str_appendc(&result, str[pos++]);
}
}
efree(key);
zend_hash_destroy(&tmp_hash);
smart_str_0(&result);
RETVAL_STRINGL(result.c, result.len, 0);
}
相关推荐:
OpenAI推出的GPT-4Turbo大幅降低了AI应用成本,推动了AI技术的普及化,ai*版
SEO与SEM:谁才是提升网站流量的王者?,Ai中字体如何变形立体
Chat免费,让沟通无界限,尽享智能对话时代,ai没办法置顶
ChatGPT无法加载?检查您的网络设置并尝试重启,轻松解决常见问题!,ai招生广告设计
SEO对策:提升网站排名与流量的必备策略,SEO入门相机平价学生
如何下载免费AI软件,让你的工作和生活更智能
GPT哪个模型是最新的?AI语言生成的未来,ai回头
SEO是什么意思?揭秘SEO的真正含义与重要性,公司推广网站询问d火18星来
SEO动态:2025年SEO趋势与优化技巧解析,十堰外贸网站推广费用
互联网资源的无限潜力:如何利用数字世界为个人和企业创造价值,信阳网站建设正规公司
为什么做seo矩阵项目,为什么做seo矩阵项目不能做 ,怎么用ai写作
seo渠道优化是什么,seo渠道推广怎么做 ,ai121333
seo重点工作是什么,seo重点工作是什么意思 ,棋谱检查ai
SEO优化顾问:让您的网站脱颖而出的秘密武器,ai ps 群
seo计算了什么,seo的常用术语 ,ai智能有意思的口令
什么是seo伪原创,seo就业前景伪原创怎么写 ,头像ai画怎么弄
ChatGPT3.5需要登录使用吗?AI使用的真相!,电脑版写作ai推荐怎么关闭
SEO网:让你的数字营销更加精准高效,开启网络引流新时代,丰县互联网网站推广优势
SEO技术如何通过优化提升网站流量与排名,四平网站优化公司
SEO外,如何提升网站整体营销效果?,文轩网络营销推广方案
ChatGPT:引领人工智能对话新时代的智能助手,Ai shiang
SEO优化如何提升网站排名,驾驭搜索引擎流量,三亚网站推广方法
ChatGPT空白对话:释放创意,开启智能对话的新世界,ai重庆南坪
SEO详解:如何优化你的网站提升排名,获得更多流量,伊春湖南网站优化推广
SEO观看:如何通过优化提升您的网站流量和品牌影响力,龙里网络营销推广
什么是seo的豆子,何为seo ,ai圆复制
SEO特点与实施策略:提升网站流量与排名的关键,定西抖音seo价格查询
seo该从什么开始,seo是什么时候开始的 ,ai写作免费英文怎么说
ChatGPT出现报错503?这些解决办法你必须知道!,粉墨ai说唱
什么是seo平台seo教程,什么是 seoseo有何价值 ,论文写作ai助手公众号
SEO职责:为网站注入流量,提升品牌竞争力,拼多多女装关键词排名
SEO怎么设置:让你的网站快速登上搜索引擎首页的秘密,Ai压印分色
seo站内关键词优化,seo关键词优化经验技巧 ,ai 优点
ChatGPT网页版内容显示不全的解决方案:如何轻松解决问题?,课件ai
《命运交错的轨迹:小说背后的无尽魅力》,seo优化huifachina
SEO努力:提升网站排名的关键策略,网站建设微企动力
ChatGPT的VPN梯子:畅享全球互联网自由,打破地域限制,一直搜Ai
什么是seo寄生虫,寄生虫seo原理 ,AI 疫
目前国内最好的AI人工智能软件:未来新篇章
AI热门软件,未来科技的钥匙
SEO新手必看:从零开始SEO优化的终极指南,随州网站优化技巧
AI一键生成文章网页版,让内容创作更简单高效
怎样利用AI写文章,轻松提升写作效率
AI缩写文档:革新文档管理与自动化的未来,ai聊天中文
seo稿件是什么意思,seo文章写作要求 ,ai写作未来展望和展望
SEO希望:如何通过SEO优化实现网站突破,迈向成功之路,品牌网站推广软件
SEO收集:如何通过有效数据收集提升网站排名,鞍山商城网站建设报价
SEM+SEO:助力企业数字化营销的双剑合璧之道,ai头像丑
seo的推广工具,seo推广软件哪个好 ,国内ai写作论文怎么样
SEO中权重是什么意思?让你迅速网站排名的核心秘密!,长颈鹿智能AI点读机