PHP的array_map和array_filter返回引用而不是新的数组。
PHP中的array_map和array_filter函数可以用于对数组进行处理,并返回处理后的新数组。然而,有时候我们希望返回的不是新数组,而是对原数组中的对象进行深拷贝(deep copy)。下面是一个关于这个的问题。
讨论中提到,当我们复制一个数组时,已经引用的对象会被复制到新数组中。但是,如果我们希望在创建新数组时对被引用的对象进行深拷贝,以便得到两个不同但相似的对象数组,就需要特别处理。讨论中给出了一种使用循环的解决方法,代码如下:
$new = array(); foreach ($old as $k => $v) { $new[$k] = clone $v; }
这段代码使用了clone关键字对对象进行深拷贝,从而得到了一个新的数组。
讨论中还提到,clone操作实际上是对对象进行浅拷贝(shallow copy),而不是深拷贝(deep copy)。对于是否进行深拷贝,取决于对象的具体实现。如果对象中包含对其他对象的引用,并且没有实现适当的__clone方法,那么拷贝的结果仍然是浅拷贝。换句话说,如果你要拷贝的对象的开发者实现得正确,那么拷贝结果就是深拷贝。
讨论中还提到,clone操作并不总是能创建独立的拷贝。具体取决于对象的实现。PHP官方文档中提到,如果对象的属性是对其他变量的引用,那么拷贝后的属性仍然是引用。
对于原数组中的对象进行深拷贝,可以使用循环结合clone关键字来实现。但需要注意,clone操作并不总是能创建独立的拷贝,具体取决于对象的实现。
问题的出现原因是当使用array_map和array_filter函数时,它们会返回一个新的数组,而不是原始数组的引用。因此,在对数组中的对象进行操作时,可能会出现引用相同对象的问题。
解决方法是使用一个名为array_copy的函数,该函数可以对数组进行深拷贝,避免引用相同对象。该函数通过遍历数组的每个元素,如果元素是数组,则递归调用array_copy函数进行拷贝,如果元素是对象,则使用clone关键字进行拷贝,否则直接将元素赋值给新数组。最后,返回新的数组。
下面是array_copy函数的代码示例:
function array_copy($arr) { $newArray = array(); foreach($arr as $key => $value) { if(is_array($value)) $newArray[$key] = array_copy($value); else if(is_object($value)) $newArray[$key] = clone $value; else $newArray[$key] = $value; } return $newArray; }
这个函数简单而有效,可以作为静态函数使用。它可以解决在使用array_map和array_filter函数时可能遇到的引用相同对象的问题。
另外,有用户在stackoverflow上偶然发现了类似的array_copy函数,并且不经意间使用了这个函数。这个函数的链接是:stackoverflow.com/a/17729234/1134804。用户在这个页面上多次浏览,但总是忽略了这个函数的答案。直到现在才意识到这个函数和自己的函数几乎完全相同。
通过使用array_copy函数,可以避免在使用array_map和array_filter函数时出现引用相同对象的问题。这个函数是一个有用的工具,可以确保每次操作数组时都得到一个新的数组,而不是原始数组的引用。
问题出现的原因是因为在使用array_map和array_filter函数时,它们返回的是数组的引用而不是新的数组。这导致在对返回的数组进行操作时,原始数组也会被修改。
解决方法是使用array_merge函数来创建原始数组的副本。例如,$array = array_merge(array(), $myArray)可以创建一个新的数组,其中包含了$myArray的所有元素。这样可以避免对原始数组的修改。
另一种解决方法是使用强制类型转换。例如,$array = (array)$myArray可以将$myArray转换为一个新的数组。这样也可以避免对原始数组的修改。
总结起来,为了避免使用array_map和array_filter函数返回的数组引用导致对原始数组的修改,可以使用array_merge函数或强制类型转换来创建数组的副本。这样可以确保对返回的数组进行操作时不会修改原始数组。