J'ai ce tableau:
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"
]
Ce que je recherche, c'est un moyen d'obtenir un tableau multiple avec uniquement les colonnes requises (array_column
n'est pas une option, car il ne me donne qu'une seule colonne).
Ce que j'ai fait
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"
//]
Le problème est qu'il semble trop décalé , car il répète deux fois cela. Est-il possible d'obtenir plusieurs colonnes sans cette solution de contournement? PHP: 5,6
Je pense que le plus gros problème est que vous perdez les clés
array (
0 =>
array (
0 => '1138',
1 => '6500722',
),
1 =>
array (
0 => '1144',
1 => '6501046',
),
2 =>
array (
0 => '113',
1 => '6294915',
);
Vous pouvez utiliser un simple foreach au lieu du 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);
}
Production
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',
),
)
le problème est qu'il semble trop lent, car il réitère deux fois ce point.
Il n'y a pas vraiment de moyen de ne pas le répéter 2 fois, mais vous ne voulez probablement pas non plus jeter les clés.
Cela dit, vous pouvez annuler récursivement les éléments dont vous ne voulez pas.
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);
Même sortie qu'avant
C'est plus facile à faire par référence. Plutôt ou non, c'est plus rapide, vous devrez tester les 2 et voir.
En guise de note finale, vous ne devez pas supposer que la clé existera ou que les clés seront un tableau à moins que vous ne les transposiez en tableau.
Vous pouvez également le faire avec un filtre matriciel
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);
}
Il y a un petit avantage en termes de performances à déclarer la fonction de filtrage en dehors de la boucle (array_map).
Si vous avez besoin de deux colonnes d'un tableau dont l'un est SKU (qui est généralement unique), vous pouvez utiliser array_column avec le troisième paramètre.
$new = array_column($arr, "product_id", "product_sku");
Cela renverra un tableau plat avec le SKU comme clé et l'ID comme valeur, ce qui rendra le tableau facile à utiliser également.
Production:
array(3) {
[6500722]=>
string(4) "1138"
[6501046]=>
string(4) "1144"
[6294915]=>
string(3) "113"
}
J'ai refactorisé l'approche élégante de @Chayan dans une fonction afin qu'elle puisse être utilisée comme array_column()
. Les clés à filtrer peuvent désormais être présentées comme un simple tableau.
C'est probablement aussi l'approche la plus rapide, car elle utilise des fonctions intégrées pour la plupart des travaux lourds.
<?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);
Si je comprends bien votre question, vous pouvez essayer une foreach traditionnelle - elle pourrait être un peu plus rapide.
function colsFromArray($array, $filterKeys) {
$newArr = [];
foreach($array as $key => $val) {
$element = [];
foreach($filterKeys as $filterKey) {
$element[$filterKey] = $val[$filterKey];
}
$newArr[] = $element;
}
}
(Pas testé)
Le problème est qu'il semble trop lent, car il répète deux fois cette
Votre code d'origine n'itère pas deux fois sur le même tableau. Vous ne pourrez pas contourner le tableau principal puis le tableau filterKeys si vous voulez avoir un tableau où chaque élément est un autre tableau d'éléments avec des clés du tableau filterKeys.
Il s'agit d'une fonction refactorisée basée sur celle de Chayan avec un renommage supplémentaire des colonnes sélectionnées:
/** 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;
}
Si vous ne souhaitez pas modifier votre matrice d'origine et souhaitez obtenir la sortie souhaitée
Utilisez la fonction array_insersect_key pour obtenir la sortie souhaitée comme suit
$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);