Php 类似于array\u search\u all-替换数组中某个值的所有实例
考虑到这些阵列:Php 类似于array\u search\u all-替换数组中某个值的所有实例,php,arrays,Php,Arrays,考虑到这些阵列: // an array of values $target = [5, 10, 15, 5, 25]; // an array of objects, direct from database // all "original" values in this array are unique (no duplicates) $replacements = [{original: 5, replacement: 7}, {original: 15, replacement: 1
// an array of values
$target = [5, 10, 15, 5, 25];
// an array of objects, direct from database
// all "original" values in this array are unique (no duplicates)
$replacements = [{original: 5, replacement: 7}, {original: 15, replacement: 155}, ..etc...];
用$replacement
数组中的替换值替换$target
中原始值的所有实例,最有效/最高效的方法是什么?预期结果:
// note that BOTH instances of the value 5 were replaced...
$result = [7, 10, 155, 7, 25];
这就是我现在拥有的,但感觉不是最理想的:
foreach ( $replacements AS $sub ) {
// I hate assignments within conditions, but DO want performance
while ( FALSE !== ($index = array_search( $sub->original, $target ) ) ) {
$target[ $index ] = $sub->replacement;
}
}
注:PHP版本为5.6
相关注释:1.
$target
数组可以包含5到30个值,但通常是10到15个值。2.
$target
数组可能包含重复的值。3.
$replacements
数组可能包含1到8个对象,但通常是2或3个对象。4.对于包含重复的
原始值的$replacements
不存在任何问题。
5.对于包含“级联”值的$replacement
,不存在任何问题。(也就是说,不必担心一个对象将值5替换为值7,然后另一个对象将值7替换为另一个值)
性能是一个问题的原因是,它可能会被调用数千次,使用不同的$target
和$replacement
值 有一些警告:如果5
将替换为7
,并且可能存在类似{original:7,replacement:15}
-的对象,它将在“非常”的循环遍历中替换先前替换的值
使用此{original:5,replacement:7},{original:7,replacement:25}
-当您期望5
变成7
时,它最终会变成25
。这可能是令人困惑和意外的循环。
以下应该是最理想的解决方案之一(特别是如果$replacements
包含大量项目):
假设我们设置了以下替换件
:
[{"original": 5, "replacement": 7}, {"original": 15, "replacement": 155},{"original": 25, "replacement": 27},{"original": 10, "replacement": 17},{"original": 15, "replacement": 255},{"original": 23, "replacement": 27},{"original": 17, "replacement": 17}]
使用附加数组($replacemented_keys
)累积已处理的密钥
$target = [5, 10, 15, 5, 25];
$target_count = count($target);
$replaced_keys = [];
foreach ($replacements as $sub) {
while (false !== ($index = array_search($sub->original, $target))
&& !in_array($index, $replaced_keys)) {
$target[$index] = $sub->replacement;
$replaced_keys[] = $index;
}
// avoiding circular repalcements and redundant iterations at one go
if (count($replaced_keys) == $target_count) break;
}
print_r($target);
输出:
Array
(
[0] => 7
[1] => 17
[2] => 155
[3] => 7
[4] => 27
)
有一些警告:如果5
将替换为7
,并且可能存在类似{original:7,replacement:15}
-的对象,它将在“非常”的循环遍历中替换先前替换的值
使用此{original:5,replacement:7},{original:7,replacement:25}
-当您期望5
变成7
时,它最终会变成25
。这可能是令人困惑和意外的循环。
以下应该是最理想的解决方案之一(特别是如果$replacements
包含大量项目):
假设我们设置了以下替换件
:
[{"original": 5, "replacement": 7}, {"original": 15, "replacement": 155},{"original": 25, "replacement": 27},{"original": 10, "replacement": 17},{"original": 15, "replacement": 255},{"original": 23, "replacement": 27},{"original": 17, "replacement": 17}]
使用附加数组($replacemented_keys
)累积已处理的密钥
$target = [5, 10, 15, 5, 25];
$target_count = count($target);
$replaced_keys = [];
foreach ($replacements as $sub) {
while (false !== ($index = array_search($sub->original, $target))
&& !in_array($index, $replaced_keys)) {
$target[$index] = $sub->replacement;
$replaced_keys[] = $index;
}
// avoiding circular repalcements and redundant iterations at one go
if (count($replaced_keys) == $target_count) break;
}
print_r($target);
输出:
Array
(
[0] => 7
[1] => 17
[2] => 155
[3] => 7
[4] => 27
)
暂定:
foreach ($target as &$item) {
foreach ($replacements as $replacement) {
if ($item == $replacement->original) {
$item = $replacement->replacement;
break;
}
}
}
假设$target的元素通常少于$replacements。中断每次都停止搜索所有替换项,因为原始项是唯一的。问题是,foreach是否比array\u搜索慢
如果替换的数组相当大,那么首先将其复制到一个数组中,并使用该数组直接查找值(而不是使用内部foreach)可能会更快:
编辑
再想一想。由于在$target中有重复值,因此不搜索替换项两次可能有一些优点:
asort($target);
$previous_item = false;
$previous_replace = false;
foreach ($target as &$item) {
if ($item==$previous_item && $previous_replace!==false) {
$item = $previous_replace;
} else {
$previous_replace = false;
foreach ($replacements as $replacement) {
if ($item == $replacement->original) {
$previous_replace = $replacement->replacement;
$previous_item = $item;
$item = $previous_replace;
break;
}
}
}
}
ksort($target);
暂定:
foreach ($target as &$item) {
foreach ($replacements as $replacement) {
if ($item == $replacement->original) {
$item = $replacement->replacement;
break;
}
}
}
假设$target的元素通常少于$replacements。中断每次都停止搜索所有替换项,因为原始项是唯一的。问题是,foreach是否比array\u搜索慢
如果替换的数组相当大,那么首先将其复制到一个数组中,并使用该数组直接查找值(而不是使用内部foreach)可能会更快:
编辑
再想一想。由于在$target中有重复值,因此不搜索替换项两次可能有一些优点:
asort($target);
$previous_item = false;
$previous_replace = false;
foreach ($target as &$item) {
if ($item==$previous_item && $previous_replace!==false) {
$item = $previous_replace;
} else {
$previous_replace = false;
foreach ($replacements as $replacement) {
if ($item == $replacement->original) {
$previous_replace = $replacement->replacement;
$previous_item = $item;
$item = $previous_replace;
break;
}
}
}
}
ksort($target);
如果使用PHP7,只需执行以下操作:$result=str\u replace(array\u column($replacements,“original”)、array\u column($replacements,“replacement”)、$target)代码>@Rizier123-哇。不知道str_replace在阵列上工作。为什么该解决方案需要PHP7?我在5.6上…而且,可能有重叠的对象,比如{original:5,replacement:7},{original:5,replacement:15}
?在文档中,他们在changelog中说,因为7“增加了输入参数成为对象数组的能力。”我认为使用str\u replace
的问题在于,一个模式可能与稍后声明的更宽模式匹配。例如,在你的例子中:5和15。如图所示,这种方法可能会有一些问题。如果使用PHP7,您只需执行以下操作:$result=str\u replace(array\u column($replacements,“original”)、array\u column($replacements,“replacement”)、$target)代码>@Rizier123-哇。不知道str_replace在阵列上工作。为什么该解决方案需要PHP7?我在5.6上…而且,可能有重叠的对象,比如{original:5,replacement:7},{original:5,replacement:15}
?在文档中,他们在changelog中说,因为7“增加了输入参数成为对象数组的能力。”我认为使用str\u replace
的问题在于,一个模式可能与稍后声明的更宽模式匹配。例如,在你的例子中:5和15。如图所示,这种方法可能有一些问题false
,当然,只是错过了这一点。至于你的第二个时刻,为什么不应该呢?您说:$replacements中的所有原始值都是唯一的。@cale_b,好的。让我想想单个$replacement
对象的一分钟,比如