千家信息网

strtr函数效率的示例分析

发表于:2025-11-16 作者:千家信息网编辑
千家信息网最后更新 2025年11月16日,这篇文章给大家分享的是有关strtr函数效率的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。最近经常要对字符串进行匹配和替换操作,之前一般使用str_replace
千家信息网最后更新 2025年11月16日strtr函数效率的示例分析

这篇文章给大家分享的是有关strtr函数效率的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

最近经常要对字符串进行匹配和替换操作,之前一般使用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);
}

感谢各位的阅读!关于"strtr函数效率的示例分析"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

字符 字符串 效率 代码 长度 函数 最大 下标 示例 分析 不错 最小 位置 内容 参数 感觉 更多 篇文章 结果 检查 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 辽宁语音网络技术分类创新服务 数据库教材信息课程设计 河南省网络安全专业大学排名 什么是广播电视网络安全 idc网络安全会议 上网能上玩游戏连接服务器失败 邯郸专业软件开发费用是多少 华为里面做软件开发怎么样 数据库顺序id生成 河南测控上位机软件开发 宝信软件开发有限公司怎么样 网络安全服务器扫描电脑文件 浙江格家网络技术有限融资 金蝶无法打开登陆的数据库 两台服务器 部署 数据库技术慕课试题 数据库数据导出json格式 东信网络技术有限公司 上海 监控 数据库连接池 怎么连接国外vpn服务器 联想服务器开机显示system 中国自然资源利用的数据库 asp 文件保存到数据库 国家网络安全散文 电大计算机网络技术专业 数据库模式更新是指什么 云服务器虚拟化 华硕笔记本音频服务器未响应 南阳手机软件开发多少钱 有关网络安全事件应急预案
0