根据另一个数组保留二维数组中每一行的元素

fis*_*lin 9 php arrays filtering php-5.6

我有这个数组:

0 => array:3 [
    "product_id" => "1138"
    "product_image" => "/resources/medias/shop/products/shop-6500720--1.png"
    "product_sku" => "6500722"
  ]
1 => array:3 [
    "product_id" => "1144"
    "product_image" => "/resources/medias/shop/products/shop-6501041--1.png"
    "product_sku" => "6501046"
  ]
2 => array:3 [
    "product_id" => "113"
    "product_image" => "/resources/medias/shop/products/shop-6294909--1.png"
    "product_sku" => "6294915"
]
Run Code Online (Sandbox Code Playgroud)

我正在寻找的是一种获取仅包含必需列的多数组的方法(array_column不是一个选项,因为它只给我 1 列)。

我做了什么

function colsFromArray($array, $keys)
{
    return array_map(function ($el) use ($keys) {
        return array_map(function ($c) use ($el) {
            return $el[$c];
        }, $keys);
    }, $array);
}

$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"
    ]
);
colsFromArray($array, array("product_id", "product_sku"));

//0 => array:3 [
//    "product_id" => "1138"
//    "product_sku" => "6500722"
//  ]
//1 => array:3 [
//    "product_id" => "1144"
//    "product_sku" => "6501046"
//  ]
//2 => array:3 [
//    "product_id" => "113"
//    "product_sku" => "6294915"
//]
Run Code Online (Sandbox Code Playgroud)

问题是它似乎太滞后了,因为它在此上迭代了两次。有没有办法在没有这种解决方法的情况下获得多列?

我正在使用 PHP5.6

And*_*eas 15

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");
Run Code Online (Sandbox Code Playgroud)

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"
}
Run Code Online (Sandbox Code Playgroud)

https://3v4l.org/UDGiO


Cha*_*yan 6

如果您不想更改原始数组并想要所需的输出

使用array_insersect_key函数获得所需的输出,如下所示

$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);
Run Code Online (Sandbox Code Playgroud)


Art*_*nix 5

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',
 );
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)

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',
  ),
)
Run Code Online (Sandbox Code Playgroud)

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);
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)

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

Sandbox