SitePoint Sponsor

User Tag List

Results 1 to 5 of 5
  1. #1
    SitePoint Addict
    Join Date
    Nov 2004
    Location
    New Jersey
    Posts
    317
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    General function to recursively array_map() for any callback function?

    I'm trying to write a function where you can recursively array_map() for any valid function.

    A specific function would be:
    PHP Code:
    function addslashes_deep($value) {
        if( 
    is_array($value) ) return array_map('addslashes_deep'$value);
        else return 
    addslashes($value);

    Here's my attempt at a general function:
    PHP Code:
    function array_map_deep($value$function) {
        if( 
    is_array($value) ) return array_map'array_map_deep'$valuearray_fill(0count($value), $function) );
        else eval(
    '$retval = '.$function.'($value);');
        return 
    $retval;

    However my code is buggy - the array keys are not kept intact. For instance given the code,
    PHP Code:
    $array = array("Review"=>"Something's happening. \"Quote here.\" And more.", array("Inside"=>'What\'s more: "And how". But not.'"Second"=>'Here. &something. Double: " Single: \' End.'), 'Last'=>'Nothing\'s happening.');
    print_r(array_map_deep($array'addslashes')); 
    My function outputs:
    PHP Code:
    Array
    (
        [
    0] => Something\'s happening. \"Quote here.\" And more.
        [1] => Array
            (
                [0] => What\'s more: \"And how\". But not.
                [1] => Here. &something. Double: \" Single: \' End.
            )

        [2] => Nothing\'s happening.

    The mapping of addslashes() seems to work, but it is remapping the array keys, e.g. "Review" to "0". The specific function, addslashes_deep(), does not have this problem.

    What is incorrect in my code?

  2. #2
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2008
    Posts
    5,757
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    PHP Code:
    function array_map_deep($array$callback) {
        
    $new = array();
        foreach (
    $array as $key => $val) {
            if (
    is_array($val)) {
                
    $new[$key] = array_map_deep($val$callback);
            } else {
                
    $new[$key] = call_user_func($callback$val);
            }
        }
        return 
    $new;


  3. #3
    SitePoint Guru
    Join Date
    Jul 2005
    Location
    Orlando
    Posts
    634
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You can also just use a variable for a function name. ex:

    PHP Code:
    $function_name$array 

  4. #4
    SitePoint Addict
    Join Date
    Nov 2004
    Location
    New Jersey
    Posts
    317
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by crmalibu View Post
    PHP Code:
    function array_map_deep($array$callback) {
        
    $new = array();
        foreach (
    $array as $key => $val) {
            if (
    is_array($val)) {
                
    $new[$key] = array_map_deep($val$callback);
            } else {
                
    $new[$key] = call_user_func($callback$val);
            }
        }
        return 
    $new;

    Thanks a lot, works like a charm

    Edit: Minor change to deal with possible non-array inputs -
    PHP Code:
    function array_map_deep($array$callback) {
        
    $new = array();
        if( 
    is_array($array) ) foreach ($array as $key => $val) {
            if (
    is_array($val)) {
                
    $new[$key] = array_map_deep($val$callback);
            } else {
                
    $new[$key] = call_user_func($callback$val);
            }
        }
        else 
    $new call_user_func($callback$array);
        return 
    $new;

    Last edited by Kadence; Jun 19, 2009 at 10:35.

  5. #5
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2008
    Posts
    5,757
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If you want to make it more robust, you might want to consider not just using is_array(), but also check if it implements ArrayAccess

    PHP Code:
    if (is_array($foo) || $foo instanceof ArrayAccess) {


    There's also array_walk_recursive(). You can just copy the array before calling it if you don't want the original modified.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •