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
对象的一分钟,比如