使用PHP替换数组中的字符串

15
如何在 PHP 中将一个子字符串替换为某个其他字符串,以对数组中所有项目进行操作?
我不想使用循环来完成。 PHP 中是否有预定义函数可以完全实现这一点?
如何在数组键上执行此操作?

4
为什么不想使用循环?听起来更像是一种心血来潮的想法,而不是明智的理由。 - Your Common Sense
1
查看array_map()函数 http://php.net/manual/zh/function.array-map.php - Daric
FYI,真正的答案在底部。PHP 的 str_replace 已经可以做到这一点。 - Gavin
1
相关页面更清晰:在二维数组的列值中替换子字符串和更改键值递归更改数组中的键值 - mickmackusa
1
即使“_如何在数组键上执行此操作?_”也是含糊不清的。您是要更改键,还是仅更改特定键的值? - mickmackusa
显示剩余3条评论
8个回答

99

为什么不直接使用 str_replace 函数而不需要循环?

$array = array('foobar', 'foobaz');
$out = str_replace('foo', 'hello', $array);

8
我很惊讶为什么发帖人没有接受这个回答。看起来他真的不知道自己在寻求什么。 - Your Common Sense
而且不仅这个答案没有被接受为正确答案,对我来说它是所有答案中最后一位的......(我正在使用活动状态进行搜索序列) - cytsunny
当我尝试使用解码后的JSON数组运行此代码时,出现了错误 PHP Catchable fatal error: Object of class stdClass could not be converted to string。我对PHP非常陌生,到目前为止编辑数组似乎很困难。 - Dennis
@Dennis:json_decode默认返回一个对象,而不是一个数组,除非你明确指定要一个数组。 - netcoder
2
Stack Overflow的逻辑:将得票最高的答案推到底部。 - Gavin
显示剩余2条评论

29
$array = array_map(
    function($str) {
        return str_replace('foo', 'bar', $str);
    },
    $array
);

但是array_map只是一个隐藏的循环。为什么不使用一个真正的循环呢?

foreach ($array as &$str) {
    $str = str_replace('foo', 'bar', $str);
}

那样容易多了。


好的,我尝试了第二个选项,但是在$str之前没有加&符号,它没有起作用。但是为什么要加&符号,在这种情况下&符号代表什么意思? - kv1dr
& 符号使变量成为指向循环中真实数组元素的指针。 - rubo77

7

我发现并成功使用了一个非常好的想法:

function str_replace_json($search, $replace, $subject) 
{
    return json_decode(str_replace($search, $replace, json_encode($subject)), true);
}

它对于多维数组也非常好用。

如果您将“true”更改为“false”,它将返回一个对象而不是关联数组。

来源:Codelinks


如果您试图替换大括号 {},那么它将无法工作。 - Max S.
这在数组上运行良好,但如果一个数组包含一个元素,它是一个对象,它将把对象转换为数组。 - rubo77
此答案会改变任何符合条件的键和/或值。它也容易产生无效的json,从而破坏脚本。 - mickmackusa

1
function my_replace_array($array,$key,$val){
    for($i=0;$i<count($array);$i++){
        if(is_array($array[$i])){
            $array[$i] = my_replace_array($array[$i],$key,$val);
        }else{
            $array[$i]=str_replace($key,$val,$array[$i]);
        }
    }
    return $array;
}

这个递归答案缺少了教育性的解释。 - mickmackusa
对象也应该被处理。 - rubo77
这个含糊的问题中没有任何关于“对象”的线索。@rubo77 - mickmackusa
“所有项目”也可以是对象,但此示例中未处理。 - rubo77
@rubo77的编辑使得这个答案无效。证据:https://3v4l.org/bqQc7 因此,应该回滚编辑,关闭页面,并允许页面继续累积删除投票。 - mickmackusa
如果有一个意图相同的更好的页面,那么你是正确的。也许将其标记为重复? - rubo77

1

我不确定这种方法的效率如何,但我想替换一个大的多维数组中的字符串,而且不想循环遍历所有项,因为数组结构非常动态。

我首先将该数组使用json_encode编码成字符串。

替换所有我想要的字符串(如果有非英文字符被json_encode编码,则需要使用preg_replace)。

json_decode以获取数组。


对于那些正在考虑使用此建议的开发者,需要注意:在 json 编码的字符串上使用 str_replace()preg_replace() 会使所有键、值和 json 格式字符易受变异的影响。可能存在一些情况下这种技术是安全的,但这种通用建议不应该被实施为一般性的方法。 - mickmackusa

0
使用array_walk_recursive()函数。
function replace_array_recursive( string $needle, string $replace, array &$haystack ){
    array_walk_recursive($haystack,
        function (&$item, $key, $data){
        $item = str_replace( $data['needle'], $data['replace'], $item );
        return $item;
    },
        [ 'needle' => $needle, 'replace' => $replace ]
    );
}

return $item; 是否真的必要? - mickmackusa

0

自 PHP 8.1 开始,不再有预定义的函数。因此,这将替换所有元素,即使存在对象:

<?php

class Arrays {
    /**
     * Replaces in all strings within a multidimensional array, even if objects are included
     * @param  string $search       search for this string
     * @param  string $replace_with replace with this string
     * @param  mixed $haystack        Array or Object to search in all elements
     * @return mixed               gives the same structure back
     */
    public static function replace_everywhere($search, $replace_with, $haystack) {
        if (is_array($haystack) or is_object($haystack)) {
            // Arrays and Objects
            foreach ($haystack as &$value) {
                $value = Arrays::replace_everywhere($search, $replace_with, $value);
            }
            return $haystack;
        } elseif (is_string($haystack)) {
            // replace in a string element
            return str_replace($search, $replace_with, $haystack);
        } else {
            // other datatypes (e.g. integer) stay untouched
            return $haystack;
        }
    }
}


// You can call this like e.g.
$a = array(true, 1, 'foo<bar', 'foo<baz', array("foo<loo"), (object) array('1' => 'foo<boo'));
$a = Arrays::replace_everywhere("<", "&lt;", $a);
var_export($a);

示例:https://3v4l.org/CDGvC#v8.2.5


如果你想要替换数组键,我认为这是另一个问题,有很好的答案,比如:递归更改数组键


你应该提出一个新的问题,包含明确的 [mcve] 并自己回答它,而不是破坏原问题只为了适应你的答案。 - mickmackusa
添加一个样本输入只是 [mcve] 的一部分。由于没有期望的输出,所以问题仍然不清楚(并且不应该重新打开)。通过调整输入数据集来适应您的答案,您可能会使先前发布的答案无效。这是不公平的行为。 - mickmackusa
你说得对,我编辑了最小的示例,以便它适用于所有答案。 - rubo77
顺便说一句:我认为“破坏”是另一回事。在这里,我只是添加了一个例子,以便这个备受搜索引擎关注的问题更加清晰,作者显然想表达什么。 - rubo77
我发现这个页面太过于出名,但实际上它代表了网站上一些最糟糕的问题——需求模糊、没有最小完整可运行示例、没有尝试和标题党。你的答案是一个过度设计的解决方案,超出了在一个扁平数组上调用str_replace()的范围。换句话说,你的答案更适合回答不同的问题。 - mickmackusa
显示剩余2条评论

-1
$base = array('citrus' => array( "orange") , 'berries' => array("blackberry", "raspberry"), );
$replacements = array('citrus' => array('pineapple'), 'berries' => array('blueberry'));
$basket = array_replace_recursive($base, $replacements);
$basket = array_replace($base, $replacements);

这个答案缺少教育性的解释。它是如何工作的?在什么情况下这种技术不适用?我知道这些答案,但研究人员不会知道--请在您的贡献中更加慷慨一些。这些不包括样本数据的旧问题的问题在于范围可以解释。我担心您正在将范围扩大到原始帖子之外,但无从得知。 - mickmackusa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接