私はこの配列を持っています:
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"
]
私が探しているのは、必要な列のみを含む複数の配列を取得する方法です(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"
//]
問題はlaggyであるように見えることです。これはこれを2回繰り返すためです。この回避策なしで複数の列を取得する方法はありますか? PHP:5.6
より大きな問題はあなたが鍵を失うことだと思います
array (
0 =>
array (
0 => '1138',
1 => '6500722',
),
1 =>
array (
0 => '1144',
1 => '6501046',
),
2 =>
array (
0 => '113',
1 => '6294915',
);
2番目のarray_mapの代わりに単純なforeachを使用できます:
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);
}
出力
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',
),
)
問題は、これを2回繰り返すため、時間がかかりすぎるように見えることです。
2回繰り返さないようにする実際の方法はありませんが、おそらくキーも捨てたくないでしょう。
つまり、不要な項目の設定を再帰的に解除できます。
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);
以前と同じ出力
これは参照することで簡単になります。どちらかと言えば、2つをテストして確認する必要があります。
最後に、キーを配列としてキャストしない限り、キーが存在する、またはそのキーが配列になると想定しないでください。
配列フィルターでそれを行うこともできます
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);
}
ループの外側でフィルタリングするための関数(array_map)を宣言すると、パフォーマンスが少し向上します。
1つがSKU(通常は一意)である配列から2つの列が必要な場合は、3番目のパラメーターでarray_columnを使用できます。
$new = array_column($arr, "product_id", "product_sku");
これにより、SKUをキーとして、IDを値として持つフラット配列が返され、配列も扱いやすくなります。
出力:
array(3) {
[6500722]=>
string(4) "1138"
[6501046]=>
string(4) "1144"
[6294915]=>
string(3) "113"
}
@Chayanからのエレガントなアプローチを関数にリファクタリングして、array_column()
のように使用できるようにしました。フィルタリングされるキーは、単純な配列として提示できるようになりました。
ところで、これは最も重いアプローチのほとんどに組み込み関数を使用するため、おそらく最も速いアプローチでもあります。
<?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);
私があなたの質問を正しく理解していれば、従来のforeachを試すことができます-少し速いかもしれません。
function colsFromArray($array, $filterKeys) {
$newArr = [];
foreach($array as $key => $val) {
$element = [];
foreach($filterKeys as $filterKey) {
$element[$filterKey] = $val[$filterKey];
}
$newArr[] = $element;
}
}
(未検証)
問題は、これを2回繰り返すため、遅すぎるように見えることです
元のコードが同じ配列で2回繰り返されていません。各要素がfilterKeys配列のキーを持つ要素の別の配列である配列が必要な場合は、メイン配列を繰り返し処理してからfilterKeys配列を回避することはできません。
これは、選択された列の名前変更が追加されたChayanに基づくリファクタリングされた関数です。
/** 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;
}
元の配列を変更せず、希望の出力が必要な場合
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);