基于另一个数组保留二维数组的每一行中的元素
Preserve elements in each row of a two-dimensional array based on another array
我有这个数组:
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"
//]
问题是它似乎太滞后,因为它对此进行了两次迭代。
如果没有此解决方法,是否有任何方法可以获取多列?
我正在使用 PHP5.6
如果我对你的问题理解正确,你可以试试传统的 foreach - 它可能会快一点。
function colsFromArray($array, $filterKeys) {
$newArr = [];
foreach($array as $val) {
$element = [];
foreach($filterKeys as $filterKey) {
$element[$filterKey] = $val[$filterKey];
}
$newArr[] = $element;
}
}
(未测试)
The problem is that it seems too laggy, since it iterates twice over this
您的原始代码没有在同一个数组上迭代两次。如果您想要一个数组,其中每个元素都是另一个元素数组,其中的键来自 filterKeys 数组,那么您将无法绕过主数组然后遍历 filterKeys 数组。
如果您需要数组中的两列,其中一列是 SKU(通常是唯一的),那么您可以将 array_column 与第三个参数一起使用。
$new = array_column($arr, "product_id", "product_sku");
这将 return 一个以 SKU 为键,ID 为值的平面数组,使该数组也易于使用。
输出:
array(3) {
[6500722]=>
string(4) "1138"
[6501046]=>
string(4) "1144"
[6294915]=>
string(3) "113"
}
我认为更大的问题是你丢失了钥匙
array (
0 =>
array (
0 => '1138',
1 => '6500722',
),
1 =>
array (
0 => '1144',
1 => '6501046',
),
2 =>
array (
0 => '113',
1 => '6294915',
);
您可以使用一个简单的 foreach 而不是第二个 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);
}
输出
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',
),
)
the problem is that it seems too laggy, since it iterates twice over this.
没有不重复它 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)。
如果您不想更改原始数组并想要您想要的输出
使用 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);
我将@Chayan 的优雅方法重构为一个函数,因此它可以像 array_column()
一样使用。要过滤的键现在可以显示为一个简单的数组。
顺便说一句,这很可能也是最快的方法,因为它使用 build-in 函数来完成大部分繁重的工作。
function array_columns(array $arr, array $keysSelect)
{
$keys = array_flip($keysSelect);
return array_map(
function($a) use($keys) {
return array_intersect_key($a,$keys);
},
$arr
);
}
$arr = [
[
"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 = ["product_id" , "product_sku"];
$filteredArray = array_columns($arr, $keysSelect);
var_dump($filteredArray);
这是一个基于 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_columns 函数的新增功能,最终追溯到 Chayan 的答案,这次是从 Joseph Mangion 的函数扩展而来。
我偶尔会有很长的选定列列表,我想在其中保留键,而不必为大量字段遵循繁琐的 ['orignal_field_name'] => ['original_field_name']
格式。
此版本默认保留每个字段的原始键,除非指定新键。
// See answer from Joseph Mangion:
/** Function - array_columns Selects columns from multidimensional array and renames columns as required
*
* @param array $in_array, array $select_columns_rename_keys
* example of $select_columns_rename_keys:
* ['new_column_name1' => 'original_column_name1', 'original_column_name2', 'original_column_name3', 'new_column_name4' => 'original_column_name4', ...]
* This will use the original keys for columns 2 and 3 and rename columns 1 and 4
* @return array
* @access public
*
*/
public function array_columns($in_array, $select_columns_rename_keys) {
foreach ($select_columns_rename_keys as $k => $v)
if (is_int($k)) {
$select_columns_rename_keys[$v] = $v;
unset($select_columns_rename_keys[$k]);
}
$keys = array_flip($select_columns_rename_keys);
$filtered_array =
array_map(function($a) use($keys) {
$data = array_intersect_key($a, $keys);
$return_array = [];
foreach ($data as $column_name => $value) $return_array[$keys[$column_name]] = $value;
return $return_array;
}, $in_array);
return $filtered_array;
}
我有这个数组:
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"
//]
问题是它似乎太滞后,因为它对此进行了两次迭代。 如果没有此解决方法,是否有任何方法可以获取多列?
我正在使用 PHP5.6
如果我对你的问题理解正确,你可以试试传统的 foreach - 它可能会快一点。
function colsFromArray($array, $filterKeys) {
$newArr = [];
foreach($array as $val) {
$element = [];
foreach($filterKeys as $filterKey) {
$element[$filterKey] = $val[$filterKey];
}
$newArr[] = $element;
}
}
(未测试)
The problem is that it seems too laggy, since it iterates twice over this
您的原始代码没有在同一个数组上迭代两次。如果您想要一个数组,其中每个元素都是另一个元素数组,其中的键来自 filterKeys 数组,那么您将无法绕过主数组然后遍历 filterKeys 数组。
如果您需要数组中的两列,其中一列是 SKU(通常是唯一的),那么您可以将 array_column 与第三个参数一起使用。
$new = array_column($arr, "product_id", "product_sku");
这将 return 一个以 SKU 为键,ID 为值的平面数组,使该数组也易于使用。
输出:
array(3) {
[6500722]=>
string(4) "1138"
[6501046]=>
string(4) "1144"
[6294915]=>
string(3) "113"
}
我认为更大的问题是你丢失了钥匙
array (
0 =>
array (
0 => '1138',
1 => '6500722',
),
1 =>
array (
0 => '1144',
1 => '6501046',
),
2 =>
array (
0 => '113',
1 => '6294915',
);
您可以使用一个简单的 foreach 而不是第二个 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);
}
输出
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',
),
)
the problem is that it seems too laggy, since it iterates twice over this.
没有不重复它 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)。
如果您不想更改原始数组并想要您想要的输出
使用 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);
我将@Chayan 的优雅方法重构为一个函数,因此它可以像 array_column()
一样使用。要过滤的键现在可以显示为一个简单的数组。
顺便说一句,这很可能也是最快的方法,因为它使用 build-in 函数来完成大部分繁重的工作。
function array_columns(array $arr, array $keysSelect)
{
$keys = array_flip($keysSelect);
return array_map(
function($a) use($keys) {
return array_intersect_key($a,$keys);
},
$arr
);
}
$arr = [
[
"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 = ["product_id" , "product_sku"];
$filteredArray = array_columns($arr, $keysSelect);
var_dump($filteredArray);
这是一个基于 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_columns 函数的新增功能,最终追溯到 Chayan 的答案,这次是从 Joseph Mangion 的函数扩展而来。
我偶尔会有很长的选定列列表,我想在其中保留键,而不必为大量字段遵循繁琐的 ['orignal_field_name'] => ['original_field_name']
格式。
此版本默认保留每个字段的原始键,除非指定新键。
// See answer from Joseph Mangion:
/** Function - array_columns Selects columns from multidimensional array and renames columns as required
*
* @param array $in_array, array $select_columns_rename_keys
* example of $select_columns_rename_keys:
* ['new_column_name1' => 'original_column_name1', 'original_column_name2', 'original_column_name3', 'new_column_name4' => 'original_column_name4', ...]
* This will use the original keys for columns 2 and 3 and rename columns 1 and 4
* @return array
* @access public
*
*/
public function array_columns($in_array, $select_columns_rename_keys) {
foreach ($select_columns_rename_keys as $k => $v)
if (is_int($k)) {
$select_columns_rename_keys[$v] = $v;
unset($select_columns_rename_keys[$k]);
}
$keys = array_flip($select_columns_rename_keys);
$filtered_array =
array_map(function($a) use($keys) {
$data = array_intersect_key($a, $keys);
$return_array = [];
foreach ($data as $column_name => $value) $return_array[$keys[$column_name]] = $value;
return $return_array;
}, $in_array);
return $filtered_array;
}