用前缀和后缀替换部分字符串
Replacing part of string with prefix and suffix
$str = ' I love [123] and [124] at (456). I hate [234] and [235] at (123).'
我想去
$str = 'I love <a title="a">[123]</a> and <a title="b">[124]</a> at <a title="XX">(456)</a>. I hate <a title="c">[234]</a> and <a title="d">[235]</a> at <a title="ZZ">(123)</a>.'
要用大括号 () 或 [] 替换的文本可以从 Table 1 或 Table 2 中找到。
Table 1
123 | a
124 | b
234 | c
235 | d
Table 2
456 | XX
123 | ZZ
当前方法
$text=explode(' ', $text);
for ($i=0; $i<count($text); $i++) {
for ($j=0; $j<count($table1Col1); $j++) {
if ($text[$i] == $table1Col1[$j])
$text[$i] = '<a href="#" title="'.$table1Col2[$j].'">'.$table1Col1[$j].'</a>';
}
for ($j=0; $j<count($table2Col1); $j++) {
if ($text[$i] == $table2Col1[$j])
$text[$i] = '<a href="#" title="'.$table2Col2[$j].'">'.$table2Col1[$j].'</a>';
}
}
如何改进代码以跳过不需要的循环?
我会考虑使用一个循环的方法,但由于数组具有相同的键,因此无法合并:
foreach($table1Col1 as $find => $repl) {
$text = str_replace("[$find]",
"<a title=\"$repl\">[$find]</a>",
$text);
}
foreach($table1Col2 as $find => $repl) {
$text = str_replace("($find)",
"<a title=\"$repl\">($find)</a>",
$text);
}
也许 preg_replace_callback
这里会更好?
$str = 'I love [123] and [124] at (456). I hate [234] and [235] at (123).';
$t1 = ['123'=>'a', '124'=>'b', '234'=>'c', '235'=>'d'];
$t2 = ['456'=>'XX', '123'=>'ZZ'];
$f1 = implode('|', array_map(fn ($k) => preg_quote($k), array_keys($t1)));
$f2 = implode('|', array_map(fn ($k) => preg_quote($k), array_keys($t2)));
$res = preg_replace_callback("/\[($f1)\]|\(($f2)\)/", function($m) use($t1, $t2) {
// if first group has matched, then found key will be in `$m[1]`
// if second group has matched, then found key will be in `$m[2]`
$m1 = $m[1] ?? null;
$m2 = $m[2] ?? null;
if ($m1) {
// use first table
return '<a title="'.$t1[$m1].'">['.$m1.']</a>';
}
// use second table
return '<a title="'.$t2[$m2].'">('.$m2.')</a>';
}, $str);
结果:
I love <a title="a">[123]</a> and <a title="b">[124]</a> at <a title="XX">(456)</a>. I hate <a title="c">[234]</a> and <a title="d">[235]</a> at <a title="ZZ">(123)</a>.
假设字符串中的所有值都出现在 table 中,您可以使用交替 |
来捕获 2 组中的每个数字,并使用该组索引到数组使用 preg_replace_callback.
的值
\[(\d+)]|\((\d+)\)
$str = ' I love [123] and [124] at (456). I hate [234] and [235] at (123).';
$table1Col1=["123" => "a", "124" => "b", "234" => "c", "235" => "d"];
$table1Col2 = ["456" => "XX", "123" => "ZZ"];
$pattern = "/\[(\d+)]|\((\d+)\)/";
$result = preg_replace_callback($pattern, function($match) use ($table1Col1, $table1Col2) {
return sprintf('<a title="%s">%s</a>',
array_key_exists(2, $match) ? $table1Col2[$match[2]] : $table1Col1[$match[1]]
, $match[0]
);
}, $str);
echo $result;
输出
I love <a title="a">[123]</a> and <a title="b">[124]</a> at <a title="XX">(456)</a>. I hate <a title="c">[234]</a> and <a title="d">[235]</a> at <a title="ZZ">(123)</a>.
$str = ' I love [123] and [124] at (456). I hate [234] and [235] at (123).'
我想去
$str = 'I love <a title="a">[123]</a> and <a title="b">[124]</a> at <a title="XX">(456)</a>. I hate <a title="c">[234]</a> and <a title="d">[235]</a> at <a title="ZZ">(123)</a>.'
要用大括号 () 或 [] 替换的文本可以从 Table 1 或 Table 2 中找到。
Table 1
123 | a
124 | b
234 | c
235 | d
Table 2
456 | XX
123 | ZZ
当前方法
$text=explode(' ', $text);
for ($i=0; $i<count($text); $i++) {
for ($j=0; $j<count($table1Col1); $j++) {
if ($text[$i] == $table1Col1[$j])
$text[$i] = '<a href="#" title="'.$table1Col2[$j].'">'.$table1Col1[$j].'</a>';
}
for ($j=0; $j<count($table2Col1); $j++) {
if ($text[$i] == $table2Col1[$j])
$text[$i] = '<a href="#" title="'.$table2Col2[$j].'">'.$table2Col1[$j].'</a>';
}
}
如何改进代码以跳过不需要的循环?
我会考虑使用一个循环的方法,但由于数组具有相同的键,因此无法合并:
foreach($table1Col1 as $find => $repl) {
$text = str_replace("[$find]",
"<a title=\"$repl\">[$find]</a>",
$text);
}
foreach($table1Col2 as $find => $repl) {
$text = str_replace("($find)",
"<a title=\"$repl\">($find)</a>",
$text);
}
也许 preg_replace_callback
这里会更好?
$str = 'I love [123] and [124] at (456). I hate [234] and [235] at (123).';
$t1 = ['123'=>'a', '124'=>'b', '234'=>'c', '235'=>'d'];
$t2 = ['456'=>'XX', '123'=>'ZZ'];
$f1 = implode('|', array_map(fn ($k) => preg_quote($k), array_keys($t1)));
$f2 = implode('|', array_map(fn ($k) => preg_quote($k), array_keys($t2)));
$res = preg_replace_callback("/\[($f1)\]|\(($f2)\)/", function($m) use($t1, $t2) {
// if first group has matched, then found key will be in `$m[1]`
// if second group has matched, then found key will be in `$m[2]`
$m1 = $m[1] ?? null;
$m2 = $m[2] ?? null;
if ($m1) {
// use first table
return '<a title="'.$t1[$m1].'">['.$m1.']</a>';
}
// use second table
return '<a title="'.$t2[$m2].'">('.$m2.')</a>';
}, $str);
结果:
I love <a title="a">[123]</a> and <a title="b">[124]</a> at <a title="XX">(456)</a>. I hate <a title="c">[234]</a> and <a title="d">[235]</a> at <a title="ZZ">(123)</a>.
假设字符串中的所有值都出现在 table 中,您可以使用交替 |
来捕获 2 组中的每个数字,并使用该组索引到数组使用 preg_replace_callback.
\[(\d+)]|\((\d+)\)
$str = ' I love [123] and [124] at (456). I hate [234] and [235] at (123).';
$table1Col1=["123" => "a", "124" => "b", "234" => "c", "235" => "d"];
$table1Col2 = ["456" => "XX", "123" => "ZZ"];
$pattern = "/\[(\d+)]|\((\d+)\)/";
$result = preg_replace_callback($pattern, function($match) use ($table1Col1, $table1Col2) {
return sprintf('<a title="%s">%s</a>',
array_key_exists(2, $match) ? $table1Col2[$match[2]] : $table1Col1[$match[1]]
, $match[0]
);
}, $str);
echo $result;
输出
I love <a title="a">[123]</a> and <a title="b">[124]</a> at <a title="XX">(456)</a>. I hate <a title="c">[234]</a> and <a title="d">[235]</a> at <a title="ZZ">(123)</a>.