PHP convert nested array to single array while concatenating keys?

前端 未结 7 972
我在风中等你
我在风中等你 2020-12-10 04:24

Here is an example array:

 $foo = array(
           \'employer\' => array(
                    \'name\' => \'Foobar Inc\',
                    \'phone\         


        
相关标签:
7条回答
  • 2020-12-10 05:02

    Here is a function which allows you to specify a top-level prefix via the second parameter:

    function flatten_array($array, $prefix = null) {
      if ($prefix) $prefix .= '_';
    
      $items = array();
    
      foreach ($array as $key => $value) {
        if (is_array($value))
          $items = array_merge($items,  flatten_array($value, $prefix . $key));
        else
          $items[$prefix . $key] = $value;
      }
    
      return $items;
    }
    
    0 讨论(0)
  • 2020-12-10 05:02

    After a few iterations, I've been able to refine a solution to this problem that uses a stack-based approach to avoid recursion, simplifying things a bit.

    /***
     * @name array_flatten
     * @author Tom Penzer @tpenzer
     * Flattens a multi-tiered array into a single-tiered 
     * associative array with keys reflective of their 
     * values' hierarchy.
     *
     * @param    array    $array       Required - the multi- 
     * level keyed array to be flattened
     * @param    string   $separator   Optional - the string 
     * used to separate the keys from different levels of 
     * the hierarchy
     *
     * @return   array    a single-level keyed array
     ***/
    function array_flatten($array, $separator = '_') {
        $output = array();
    
        while (list($key, $value) = each($array)) {
            if (is_array($value)) {
                $build = array();
                foreach ($value as $s_key => $s_value) {
                    $build[$key . $separator . $s_key] = $s_value;
                }
                unset($array[$key]);
                $array = $build + $array;
                unset($build);
                continue;//skip write to $output
            }
            $output[$key] = $value;
            unset($array[$key]);
        }
    
        return $output;
    }
    

    Not exactly the method requested, but it's a nice contrast to the recursive approaches to the problem.

    0 讨论(0)
  • 2020-12-10 05:05

    This will flatten a multidimensional associative array tacking a digit to the key if its a duplicate. If you don't mind having a digit index to differentiate duplicate keys instead of concatenated keys this could be a solution.

    $result = array();
    array_walk_recursive($your_array, function($v, $k) use (&$result){ $i = ""; for (; isset($result[$k."$i"]); $i++); $result[$k."$i"] = $v; });
    

    I suspect it could be worked on further to do concatenated keys.

    The above solution is basically for doing this kind of thing

    <?php
        $xml_str = "
        <images>
            <image>
                <position>0</position>                  
            </image>
            <image1>
                <position>10</position>
            </image1>
        </images>";
                        // turn the xml into a multidimentional array
                $ob = simplexml_load_string($xml_str);
                $json = json_encode($ob);
                $my_array = json_decode($json, true);
    
                print_r($my_array);
                        // flatten it
                $result = array();
                array_walk_recursive($my_array, function($v, $k) use (&$result){ $i = ""; for (; isset($result[$k."$i"]); $i++); $result[$k."$i"] = $v; });
    
                print_r($result);
    ?>
    
    0 讨论(0)
  • 2020-12-10 05:06

    I think this 'trick' using is http_build_query is less of an eyesore w/out recursion (or at least letting php do it for you)

    3 lines of code if your str_replace uses the url-encoded values for [ and ]

    $string      = http_build_query($array);
    $string      = urldecode($string);
    $string      = str_replace(
                        array('[',']'),
                        array('_','') , 
                        $string
                    );
    parse_str($string, $flat_array);
    

    $flat_array becomes :

    array(7) {
      ["employer_name"]         =>"Foobar Inc"
      ["employer_phone"]        =>"555-555-5555"
      ["employee_name"]         =>"John Doe"
      ["employee_phone"]        =>"555-555-5556"
      ["employee_address_state"]=>"California"
      ["employee_address_zip"]  =>"90210"
      ["modified"]              =>"2009-12-01"
    }
    
    0 讨论(0)
  • 2020-12-10 05:07

    Something like this:

    function makeNonNestedRecursive(array &$out, $key, array $in){
        foreach($in as $k=>$v){
            if(is_array($v)){
                makeNonNestedRecursive($out, $key . $k . '_', $v);
            }else{
                $out[$key . $k] = $v;
            }
        }
    }
    
    function makeNonNested(array $in){
        $out = array();
        makeNonNestedRecursive($out, '', $in);
        return $out;
    }
    
    // Example
    $fooCompressed = makeNonNested($foo);
    
    0 讨论(0)
  • 2020-12-10 05:17

    A solution whith only array_* php functions + recursive :

    $array = array(
        "level1"=>"value",
        "level2" => ["level11" => "value", "level21" => "value"],
        "level3" => ["level2" => ["level1" => "value"]],
        "level4" => ["level3" => ["level2" => ["level1" => "value"]]],
        "level5" => ["level4" => ["level3" => ["level2" => ["level1" => "value"]]]],
    );
     
    //flatten array with combined keys
    function arrayFlat($array) {
        $result = [];
        array_walk($array, function($v, $pk)use(&$result){
            if(is_array($v)) {
                $result += arrayFlat(array_combine(
                    array_map(function($k) use($pk){ return $pk . '_' .$k; }, array_keys($v)),
                    $v
                ));
            } else {
                $result[$pk] = $v;
            }
        });
        return $result;
    }
    
    print_r(arrayFlat($array));
    

    Output :

    Array
    (
        [level1] => value
        [level2_level11] => value
        [level2_level21] => value
        [level3_level2_level1] => value
        [level4_level3_level2_level1] => value
        [level5_level4_level3_level2_level1] => value
    )
    
    0 讨论(0)
提交回复
热议问题