PHP - get multiple columns from array

后端 未结 7 1847
星月不相逢
星月不相逢 2021-01-12 09:55

I have this array:

0 => array:3 [
    \"product_id\" => \"1138\"
    \"product_image\" => \"/resources/medias/shop/products/shop-6500720--1.png\"
           


        
相关标签:
7条回答
  • 2021-01-12 10:18

    If you do not want to change your original array and want your desired output

    Use array_insersect_key function to get your desired output as following

    $array = array(
        [
            "product_id"    => "1138",
            "product_image" => "/resources/medias/shop/products/shop-6500720--1.png",
            "product_sku"   => "6500722"
        ],
        [
            "product_id"    => "1144",
            "product_image" => "/resources/medias/shop/products/shop-6501041--1.png",
            "product_sku"   => "6501046"
        ],
        [
            "product_id"    => "113",
            "product_image" => "/resources/medias/shop/products/shop-6294909--1.png",
            "product_sku"   => "6294915"
        ]
    );
    
    $keys = array("product_id"=>1, "product_sku"=>2);
    
    $filteredArray = array_map(function($a) use($keys){
        return array_intersect_key($a,$keys);
    }, $array);
    
    print_r($filteredArray);
    
    0 讨论(0)
  • 2021-01-12 10:21

    I refactored the elegant approach from @Chayan into a function so it can be used like array_column(). Keys to be filtered can now be presented as a simple array.

    Btw this is most likely also the fastest approach, since it uses build-in functions for most of the heavy lifting.

    <?php
    
    function array_columns(array $arr, array $keysSelect)
    {    
        $keys = array_flip($keysSelect);
        $filteredArray = array_map(function($a) use($keys){
            return array_intersect_key($a,$keys);
        }, $arr);
    
        return $filteredArray;
    }
    
    $arr = array(
        [
            "product_id"    => "1138",
            "product_image" => "/resources/medias/shop/products/shop-6500720--1.png",
            "product_sku"   => "6500722"
        ],
        [
            "product_id"    => "1144",
            "product_image" => "/resources/medias/shop/products/shop-6501041--1.png",
            "product_sku"   => "6501046"
        ],
        [
            "product_id"    => "113",
            "product_image" => "/resources/medias/shop/products/shop-6294909--1.png",
            "product_sku"   => "6294915"
        ]
    );
    
    $keysSelect = array("product_id" , "product_sku");
    $filteredArray = array_colums($arr, $keysSelect);
    
    var_dump($filteredArray);
    
    0 讨论(0)
  • 2021-01-12 10:22

    If you need two columns from an array where one is SKU (which generally is unique) then you can use array_column with the third parameter.

    $new = array_column($arr, "product_id", "product_sku");
    

    This will return a flat array with the SKU as the key and ID as value making the array easy to work with also.

    Output:

    array(3) {
      [6500722]=>
      string(4) "1138"
      [6501046]=>
      string(4) "1144"
      [6294915]=>
      string(3) "113"
    }
    

    https://3v4l.org/UDGiO

    0 讨论(0)
  • 2021-01-12 10:29

    I think the bigger issue is you lose the keys

    Original Code

    array (
      0 => 
      array (
        0 => '1138',
        1 => '6500722',
      ),
      1 => 
      array (
        0 => '1144',
        1 => '6501046',
      ),
      2 => 
      array (
        0 => '113',
        1 => '6294915',
     );
    

    You can use a simple foreach instead of the second array_map:

    function colsFromArray(array $array, $keys)
    {
        if (!is_array($keys)) $keys = [$keys];
        return array_map(function ($el) use ($keys) {
            $o = [];
            foreach($keys as $key){
                //  if(isset($el[$key]))$o[$key] = $el[$key]; //you can do it this way if you don't want to set a default for missing keys.
                $o[$key] = isset($el[$key])?$el[$key]:false;
            }
            return $o;
        }, $array);
    }
    

    Output

    array (
      0 => 
      array (
        'product_id' => '1138',
        'product_sku' => '6500722',
      ),
      1 => 
      array (
        'product_id' => '1144',
        'product_sku' => '6501046',
      ),
      2 => 
      array (
        'product_id' => '113',
        'product_sku' => '6294915',
      ),
    )
    

    Sandbox

    the problem is that it seems too laggy, since it iterates twice over this.

    There is no real way to not iterate over it 2 times, but you probably don't want to throw away the keys either.

    That said you can recursively unset the items you don't want.

    function colsFromArray(array &$array, $keys)
    {
        if (!is_array($keys)) $keys = [$keys];
        foreach ($array as $key => &$value) {
            if (is_array($value)) {
                colsFromArray($value, $keys); //recursive
            }else if(!in_array($key, $keys)){
               unset($array[$key]); 
            }
        }
    }
    
    colsFromArray($array, array("product_id", "product_sku"));
    var_export($array);
    

    Same output as before

    This is easier to do by reference. Rather or not that is faster you'll have to test the 2 and see.

    Sandbox

    As a final note you shouldn't assume the key will exist or that keys will be an array unless you type cast it as an array.

    You could also do it with array filter

    function colsFromArray(array $array, $keys)
    {
        if (!is_array($keys)) $keys = [$keys];
        $filter = function($k) use ($keys){
           return in_array($k,$keys);
        };
        return array_map(function ($el) use ($keys,$filter) {
            return array_filter($el, $filter, ARRAY_FILTER_USE_KEY );
        }, $array);
    }
    

    There is some small performance benefit to declaring the function for filtering outside of the loop (array_map).

    Sandbox

    0 讨论(0)
  • 2021-01-12 10:32

    If I understand your question correctly, you could try a traditional foreach - it might be a little faster.

    function colsFromArray($array, $filterKeys) {
        $newArr = [];
        foreach($array as $key => $val) {
           $element = [];
           foreach($filterKeys as $filterKey) {
              $element[$filterKey] = $val[$filterKey];
           }
           $newArr[] = $element;
        }
    }
    

    (Not tested)

    The problem is that it seems too laggy, since it iterates twice over this

    Your original code isn't iterating twice over the same array. You won't be able to get around iterating over the main array and then the filterKeys array if you want to have an array where each element is another array of elements with keys from the filterKeys array.

    0 讨论(0)
  • 2021-01-12 10:36

    This is a refactored function based on Chayan's with added renaming of selected columns:


     /** Function - array_columns  Selects columns from multidimantional array and renames columns as required
     *
     * @param  array $arr, array $selectColRenameKeys 
     *            example: (NewName1->colNameneeded1,NewName2->colNameneeded2,ect...)
     * @return array
     * @access public
     * 
     */   
    
     private function array_columns( $arr,$selectColRenameKeys) {    
        $keys = array_flip($selectColRenameKeys);
        $filteredArray = array_map(function($a) use($keys){
                                      $data = array_intersect_key($a,$keys);
                                      $rename_arr= array();
                                      foreach ($data as $colname => $value){
                                        $r_arr[$keys[$colname]]= $value   ;
                                      }
                                      return $r_arr;
                                   }, $arr);
    
        return $filteredArray;
    }
    
    0 讨论(0)
提交回复
热议问题