从重新使用的数组中删除先前迭代的数据
Remove previous iteration's data from re-used array
我有两个数组,$array1
和 $array2
。 $array2
是数组的数组。对于 $array2
的每个子数组,我想打印 $array1
,但要打印其他条目,这些条目取决于 $array2
子数组是否具有键 "a"
或 "c"
,值为 1
。我的代码在每个循环中打印 $array1
,但在 $array1
中还有我没有预料到的后续迭代的其他条目。为什么我会收到这些条目,我该如何防止它们?
示例代码:
$array1 = array(
"service" => "coding",
"data" => array(
"ITEM" => array(
array(
"CODE" => "9999", //STANDARD
"QUANTITY" => 1
),
)
)
);
$array2 = array(
array(
"a" => "1",
"b" => "1",
"c" => "1",
"d" => "1",
),
array(
"cancel" => "1",
"a" => "1",
"b" => "",
"c" => "",
"d" => "1",
),
array(
"cancel" => "1",
"a" => "",
"b" => "1",
"c" => "1",
"d" => "",
),
);
for ($i = 0; $i < count($array2); $i++) {
foreach ($array2[$i] as $key => $value) {
if($key == 'a' && $value == 1){
array_push($array1['data']['ITEM'],
array('SOMETHING' => 'this_is_a',
'ELSE' => "1"
)
);
}
if($key == 'c' && $value == 1){
array_push($array1['data']['ITEM'],
array('SOMETHING' => 'this_is_c',
'ELSE' => "1"
)
);
}
}
echo "Loop #$i result:\n";
var_export($array1);
echo "\n";
}
您可以将上述代码作为 PHP Sandbox snippet.
进行测试
实际结果是:
Loop #0 result:
array (
'service' => 'coding',
'data' =>
array (
'ITEM' =>
array (
0 =>
array (
'CODE' => '9999',
'QUANTITY' => 1,
),
1 =>
array (
'SOMETHING' => 'this_is_a',
'ELSE' => '1',
),
2 =>
array (
'SOMETHING' => 'this_is_c',
'ELSE' => '1',
),
),
),
)
Loop #1 result:
array (
'service' => 'coding',
'data' =>
array (
'ITEM' =>
array (
0 =>
array (
'CODE' => '9999',
'QUANTITY' => 1,
),
1 =>
array (
'SOMETHING' => 'this_is_a',
'ELSE' => '1',
),
2 =>
array (
'SOMETHING' => 'this_is_c',
'ELSE' => '1',
),
3 =>
array (
'SOMETHING' => 'this_is_a',
'ELSE' => '1',
),
),
),
)
Loop #2 result:
array (
'service' => 'coding',
'data' =>
array (
'ITEM' =>
array (
0 =>
array (
'CODE' => '9999',
'QUANTITY' => 1,
),
1 =>
array (
'SOMETHING' => 'this_is_a',
'ELSE' => '1',
),
2 =>
array (
'SOMETHING' => 'this_is_c',
'ELSE' => '1',
),
3 =>
array (
'SOMETHING' => 'this_is_a',
'ELSE' => '1',
),
4 =>
array (
'SOMETHING' => 'this_is_c',
'ELSE' => '1',
),
),
),
)
循环 #0 结果正确,但后面的循环在 $array1['data']['ITEM']
中有其他条目。期望的结果:
Loop #0 result:
array (
'service' => coding
'data' => array (
'ITEM' => array (
0 => array (
'CODE' => 9999
'QUANTITY' => 1
)
1 => array (
'SOMETHING' => 'this_is_a'
'ELSE' => 1
)
2 => array (
'SOMETHING' => 'this_is_c'
'ELSE' => 1
)
)
)
)
Loop #1 result:
array (
'service' => coding
'data' => array (
'ITEM' => array (
0 => array (
'CODE' => 9999
'QUANTITY' => 1
)
1 => array (
'SOMETHING' => 'this_is_a'
'ELSE' => 1
)
)
)
)
Loop #2 result:
array (
'service' => coding
'data' => array (
'ITEM' => array (
0 => array (
'CODE' => 9999
'QUANTITY' => 1
)
1 => array (
'SOMETHING' => 'this_is_c'
'ELSE' => 1
)
)
)
)
您可以使用 array_map
循环遍历第二个数组,并且仅在当前迭代具有名为 a
的键且其值为 [= 时才推送到第一个数组的 ['data']['ITEM']
14=].
$arr1 = [
'service' => 'coding',
'data' => [
'ITEM' => [
[
'CODE' => '9999',
'QUANTITY' => 1
]
]
]
];
$arr2 = [
[
'a' => '1',
'b' => '1',
'c' => '1',
'd' => '1',
],
[
'cancel' => '1',
'a' => '1',
'b' => '',
'c' => '',
'd' => '1',
],
[
'cancel' => '1',
'a' => '',
'b' => '1',
'c' => '1',
'd' => '',
],
];
// loop through the second array ($arr2)
// the "use" is very important here as it let's the callback function to access $arr1 variable
$finalArr = array_map(function ($el) use ($arr1) {
// if in the current iteration a kley named "a" and its value is "1" is found then push it to the first array's ['data']['ITEM'] key.
// $arr1 here is passed by value so the real array won't be channged, we're, more or less, working with copy of $arr1 in the function.
isset($el['a']) && $el['a'] == 1 && ($arr1['data']['ITEM'][] = [
'something' => 'This is a', // tried to keep same output as yours
'else' => $el['a'] // tried to keep same output as yours
]);
// for "c" key
isset($el['c']) && $el['c'] == 1 && ($arr1['data']['ITEM'][] = [
'something' => 'This is c', // tried to keep same output as yours
'else' => $el['c'] // tried to keep same output as yours
]);
// return the $arr1 copy regardless of whether we pushed "a" key or not.
return $arr1;
}, $arr2);
// print the resulting array
print_r($finalArr);
结果(样本数据):
array(
0 => array(
'service' => 'coding',
'data' => array(
'ITEM' => array(
0 => array(
'CODE' => '9999',
'QUANTITY' => 1,
),
1 => array(
'something' => 'This is a',
'else' => '1',
),
2 => array(
'something' => 'This is c',
'else' => '1',
),
),
),
),
1 => array(
'service' => 'coding',
'data' => array(
'ITEM' => array(
0 => array(
'CODE' => '9999',
'QUANTITY' => 1,
),
1 => array(
'something' => 'This is a',
'else' => '1',
),
),
),
),
2 => array(
'service' => 'coding',
'data' => array(
'ITEM' => array(
0 => array(
'CODE' => '9999',
'QUANTITY' => 1,
),
1 => array(
'something' => 'This is c',
'else' => '1',
),
),
),
),
)
您可以在 PHP 手册中了解有关 callback functions
(匿名函数)的更多信息。
您不会在每次迭代之间将 $array1['data']['ITEM']
返回到其原始状态。只需在 for()
和 foreach()
之间写下以下内容即可。
$array1['data']['ITEM'] = array_slice($array1['data']['ITEM'], 0, 1);
因为数组键必须是唯一的,所以您不需要遍历所有元素来查看 a
或 c
是否存在——这将花费不必要的循环。
此外,我发现数组解构是一个很好的选择,可以隔离您寻求的仅有的两个值。
我可能会推荐这个更简单、更直观的片段:(Demo)
foreach ($array2 as $i => ['a' => $a, 'c' => $c]) {
$temp = $array1;
if($a == 1) {
$temp['data']['ITEM'][] = [
'SOMETHING' => 'this_is_a',
'ELSE' => '1'
];
}
if ($c == 1) {
$temp['data']['ITEM'][] = [
'SOMETHING' => 'this_is_c',
'ELSE' => '1'
];
}
echo "Loop #$i result:\n";
var_export($temp);
echo "\n";
}
出现意外条目是因为 $array1
在每次迭代中都被修改(具体来说,由 array_push
修改)。为防止这种情况,每次迭代都必须对 $array1
的不同副本进行操作。由于 variable assignment and argument passing will each copy an array, either could be used. Similar to argument passing, closures 可以从外部范围继承(注意:不是 OOP 意义上的)变量,绑定到它们的值(这将复制一个数组),为解决方案提供第三个潜在基础。
需要最少编辑量的修复方法是在循环开始时将 $array1
分配给另一个变量,并在循环的其余部分用此变量替换 $array1
:
for ($i = 0; $i < count($array2); $i++) {
$result = $array1;
// ...
或者,通过将循环体移动到函数中,$array1
成为函数体中的副本:
function process(array $options, array $output) {
// Ensure entries to test are present:
$options += ['a' => NULL, 'c' => NULL];
/* As an alternative to the above, if entries should be added
* to $output whenever 'a' or 'c' has a truthy value,
* `! empty(...)` could be used instead of the `... == 1`
* tests below.
*/
if ($options['a'] == 1) {
$output['data']['ITEM'][] = [
'SOMETHING' => 'this_is_a',
'ELSE' => 1,
];
}
if ($options['c'] == 1) {
$output['data']['ITEM'][] = [
'SOMETHING' => 'this_is_c',
'ELSE' => 1,
];
}
return $output;
}
foreach ($array2 as $i => $subarray) {
echo "// Loop #$i result:";
var_export( process($subarray, $array1) );
echo ";\n";
}
作为第三种方法,您可以应用 array_map
to $array2
, as is done by 。为了进行比较,可以将前面的 foreach
循环替换为对 array_map
:
的调用
var_export(
array_map(function (array $subarray) use ($array1) {
return process($subarray, $array1);
}, $array2)
);
或者,使用 arrow function(自动使用外部作用域中的变量):
var_export(
array_map(
fn (array $subarray) => process($subarray, $array1),
$array2
) );
请注意,对于不会被修改(或修改无关紧要)的数组,您可以 pass them by reference(或在闭包中通过引用绑定)以避免复制它们的开销。
function process(array &$options, array $output) {
// ...
我有两个数组,$array1
和 $array2
。 $array2
是数组的数组。对于 $array2
的每个子数组,我想打印 $array1
,但要打印其他条目,这些条目取决于 $array2
子数组是否具有键 "a"
或 "c"
,值为 1
。我的代码在每个循环中打印 $array1
,但在 $array1
中还有我没有预料到的后续迭代的其他条目。为什么我会收到这些条目,我该如何防止它们?
示例代码:
$array1 = array(
"service" => "coding",
"data" => array(
"ITEM" => array(
array(
"CODE" => "9999", //STANDARD
"QUANTITY" => 1
),
)
)
);
$array2 = array(
array(
"a" => "1",
"b" => "1",
"c" => "1",
"d" => "1",
),
array(
"cancel" => "1",
"a" => "1",
"b" => "",
"c" => "",
"d" => "1",
),
array(
"cancel" => "1",
"a" => "",
"b" => "1",
"c" => "1",
"d" => "",
),
);
for ($i = 0; $i < count($array2); $i++) {
foreach ($array2[$i] as $key => $value) {
if($key == 'a' && $value == 1){
array_push($array1['data']['ITEM'],
array('SOMETHING' => 'this_is_a',
'ELSE' => "1"
)
);
}
if($key == 'c' && $value == 1){
array_push($array1['data']['ITEM'],
array('SOMETHING' => 'this_is_c',
'ELSE' => "1"
)
);
}
}
echo "Loop #$i result:\n";
var_export($array1);
echo "\n";
}
您可以将上述代码作为 PHP Sandbox snippet.
进行测试实际结果是:
Loop #0 result: array ( 'service' => 'coding', 'data' => array ( 'ITEM' => array ( 0 => array ( 'CODE' => '9999', 'QUANTITY' => 1, ), 1 => array ( 'SOMETHING' => 'this_is_a', 'ELSE' => '1', ), 2 => array ( 'SOMETHING' => 'this_is_c', 'ELSE' => '1', ), ), ), ) Loop #1 result: array ( 'service' => 'coding', 'data' => array ( 'ITEM' => array ( 0 => array ( 'CODE' => '9999', 'QUANTITY' => 1, ), 1 => array ( 'SOMETHING' => 'this_is_a', 'ELSE' => '1', ), 2 => array ( 'SOMETHING' => 'this_is_c', 'ELSE' => '1', ), 3 => array ( 'SOMETHING' => 'this_is_a', 'ELSE' => '1', ), ), ), ) Loop #2 result: array ( 'service' => 'coding', 'data' => array ( 'ITEM' => array ( 0 => array ( 'CODE' => '9999', 'QUANTITY' => 1, ), 1 => array ( 'SOMETHING' => 'this_is_a', 'ELSE' => '1', ), 2 => array ( 'SOMETHING' => 'this_is_c', 'ELSE' => '1', ), 3 => array ( 'SOMETHING' => 'this_is_a', 'ELSE' => '1', ), 4 => array ( 'SOMETHING' => 'this_is_c', 'ELSE' => '1', ), ), ), )
循环 #0 结果正确,但后面的循环在 $array1['data']['ITEM']
中有其他条目。期望的结果:
Loop #0 result: array ( 'service' => coding 'data' => array ( 'ITEM' => array ( 0 => array ( 'CODE' => 9999 'QUANTITY' => 1 ) 1 => array ( 'SOMETHING' => 'this_is_a' 'ELSE' => 1 ) 2 => array ( 'SOMETHING' => 'this_is_c' 'ELSE' => 1 ) ) ) ) Loop #1 result: array ( 'service' => coding 'data' => array ( 'ITEM' => array ( 0 => array ( 'CODE' => 9999 'QUANTITY' => 1 ) 1 => array ( 'SOMETHING' => 'this_is_a' 'ELSE' => 1 ) ) ) ) Loop #2 result: array ( 'service' => coding 'data' => array ( 'ITEM' => array ( 0 => array ( 'CODE' => 9999 'QUANTITY' => 1 ) 1 => array ( 'SOMETHING' => 'this_is_c' 'ELSE' => 1 ) ) ) )
您可以使用 array_map
循环遍历第二个数组,并且仅在当前迭代具有名为 a
的键且其值为 [= 时才推送到第一个数组的 ['data']['ITEM']
14=].
$arr1 = [
'service' => 'coding',
'data' => [
'ITEM' => [
[
'CODE' => '9999',
'QUANTITY' => 1
]
]
]
];
$arr2 = [
[
'a' => '1',
'b' => '1',
'c' => '1',
'd' => '1',
],
[
'cancel' => '1',
'a' => '1',
'b' => '',
'c' => '',
'd' => '1',
],
[
'cancel' => '1',
'a' => '',
'b' => '1',
'c' => '1',
'd' => '',
],
];
// loop through the second array ($arr2)
// the "use" is very important here as it let's the callback function to access $arr1 variable
$finalArr = array_map(function ($el) use ($arr1) {
// if in the current iteration a kley named "a" and its value is "1" is found then push it to the first array's ['data']['ITEM'] key.
// $arr1 here is passed by value so the real array won't be channged, we're, more or less, working with copy of $arr1 in the function.
isset($el['a']) && $el['a'] == 1 && ($arr1['data']['ITEM'][] = [
'something' => 'This is a', // tried to keep same output as yours
'else' => $el['a'] // tried to keep same output as yours
]);
// for "c" key
isset($el['c']) && $el['c'] == 1 && ($arr1['data']['ITEM'][] = [
'something' => 'This is c', // tried to keep same output as yours
'else' => $el['c'] // tried to keep same output as yours
]);
// return the $arr1 copy regardless of whether we pushed "a" key or not.
return $arr1;
}, $arr2);
// print the resulting array
print_r($finalArr);
结果(样本数据):
array( 0 => array( 'service' => 'coding', 'data' => array( 'ITEM' => array( 0 => array( 'CODE' => '9999', 'QUANTITY' => 1, ), 1 => array( 'something' => 'This is a', 'else' => '1', ), 2 => array( 'something' => 'This is c', 'else' => '1', ), ), ), ), 1 => array( 'service' => 'coding', 'data' => array( 'ITEM' => array( 0 => array( 'CODE' => '9999', 'QUANTITY' => 1, ), 1 => array( 'something' => 'This is a', 'else' => '1', ), ), ), ), 2 => array( 'service' => 'coding', 'data' => array( 'ITEM' => array( 0 => array( 'CODE' => '9999', 'QUANTITY' => 1, ), 1 => array( 'something' => 'This is c', 'else' => '1', ), ), ), ), )
您可以在 PHP 手册中了解有关 callback functions
(匿名函数)的更多信息。
您不会在每次迭代之间将 $array1['data']['ITEM']
返回到其原始状态。只需在 for()
和 foreach()
之间写下以下内容即可。
$array1['data']['ITEM'] = array_slice($array1['data']['ITEM'], 0, 1);
因为数组键必须是唯一的,所以您不需要遍历所有元素来查看 a
或 c
是否存在——这将花费不必要的循环。
此外,我发现数组解构是一个很好的选择,可以隔离您寻求的仅有的两个值。
我可能会推荐这个更简单、更直观的片段:(Demo)
foreach ($array2 as $i => ['a' => $a, 'c' => $c]) {
$temp = $array1;
if($a == 1) {
$temp['data']['ITEM'][] = [
'SOMETHING' => 'this_is_a',
'ELSE' => '1'
];
}
if ($c == 1) {
$temp['data']['ITEM'][] = [
'SOMETHING' => 'this_is_c',
'ELSE' => '1'
];
}
echo "Loop #$i result:\n";
var_export($temp);
echo "\n";
}
出现意外条目是因为 $array1
在每次迭代中都被修改(具体来说,由 array_push
修改)。为防止这种情况,每次迭代都必须对 $array1
的不同副本进行操作。由于 variable assignment and argument passing will each copy an array, either could be used. Similar to argument passing, closures 可以从外部范围继承(注意:不是 OOP 意义上的)变量,绑定到它们的值(这将复制一个数组),为解决方案提供第三个潜在基础。
需要最少编辑量的修复方法是在循环开始时将 $array1
分配给另一个变量,并在循环的其余部分用此变量替换 $array1
:
for ($i = 0; $i < count($array2); $i++) {
$result = $array1;
// ...
或者,通过将循环体移动到函数中,$array1
成为函数体中的副本:
function process(array $options, array $output) {
// Ensure entries to test are present:
$options += ['a' => NULL, 'c' => NULL];
/* As an alternative to the above, if entries should be added
* to $output whenever 'a' or 'c' has a truthy value,
* `! empty(...)` could be used instead of the `... == 1`
* tests below.
*/
if ($options['a'] == 1) {
$output['data']['ITEM'][] = [
'SOMETHING' => 'this_is_a',
'ELSE' => 1,
];
}
if ($options['c'] == 1) {
$output['data']['ITEM'][] = [
'SOMETHING' => 'this_is_c',
'ELSE' => 1,
];
}
return $output;
}
foreach ($array2 as $i => $subarray) {
echo "// Loop #$i result:";
var_export( process($subarray, $array1) );
echo ";\n";
}
作为第三种方法,您可以应用 array_map
to $array2
, as is done by foreach
循环替换为对 array_map
:
var_export(
array_map(function (array $subarray) use ($array1) {
return process($subarray, $array1);
}, $array2)
);
或者,使用 arrow function(自动使用外部作用域中的变量):
var_export(
array_map(
fn (array $subarray) => process($subarray, $array1),
$array2
) );
请注意,对于不会被修改(或修改无关紧要)的数组,您可以 pass them by reference(或在闭包中通过引用绑定)以避免复制它们的开销。
function process(array &$options, array $output) {
// ...