PHP数组合并,忽略某些重复键,让它们包含在内部创建的数组中
PHP array merging, ignore certain duplicated keys and let them be included in the inner created arrays
我将具有相同集合内部数组名称的数组合并在一起,将键值更改为订单号,然后为未与此代码重复的项目创建更多内部数组...
function readCSV($csvFile)
{
$line_of_text = [];
$file_handle = fopen($csvFile, 'r');
//skip csv headers
//fgetcsv($file_handle);
//fgetcsv($file_handle);
fgetcsv($file_handle);
while (!feof($file_handle)) {
$tmp = fgetcsv($file_handle, 1024);
if (isset($line_of_text[$tmp[0]])) {
foreach ($tmp as $k => $v) {
if (array_key_exists($k, $line_of_text[$tmp[0]])) {
if (!is_array($line_of_text[$tmp[0]][$k])) {
$kVal = $line_of_text[$tmp[0]][$k];
$line_of_text[$tmp[0]][$k] = [];
$line_of_text[$tmp[0]][$k][] = $kVal;
}
$line_of_text[$tmp[0]][$k][] = $v;
$line_of_text[$tmp[0]][$k] = array_unique($line_of_text[$tmp[0]][$k]);
$line_of_text[$tmp[0]][$k] = array_filter($line_of_text[$tmp[0]][$k]);
if (count($line_of_text[$tmp[0]][$k]) == 1) {
$line_of_text[$tmp[0]][$k] = array_values($line_of_text[$tmp[0]][$k]);
$line_of_text[$tmp[0]][$k] = $line_of_text[$tmp[0]][$k][0];
}
if (empty($line_of_text[$tmp[0]][$k])) {
$line_of_text[$tmp[0]][$k] = null;
}
} else {
$line_of_text[$tmp[0]][$k] = null;
}
}
$line_of_text[$tmp[0]][0] = $tmp[0];
} else {
$line_of_text[$tmp[0]] = $tmp;
}
}
fclose($file_handle);
return array_filter(array_values($line_of_text));
}
// Set path to CSV file
$csvFile = 'my.csv';
$csv = readCSV($csvFile);
//$csv is your array
foreach($csv as $key => $value){
if(!array_key_exists(@$value[0],$arr)){
$arr[@$value[0]] = [];
}
$arr[@$value[0]] = array_merge($arr[@$value[0]],$value);
}
echo "<pre>";
print_r($arr);
echo '</pre>';
这轮..
Array
(
[0] => Array
(
[0] => 15304
[1] => item1
[2] => qty = 1
)
[1] => Array
(
[0] => 15304
[1] => item2
[2] => qty = 1
)
[2] => Array
(
[0] => 15305
[1] => itemX
[2] => qty = 2
)
}
进入
Array
(
[15304] => Array
(
[0] => 15304
[1] => Array
(
[0]item1
[1]item2
)
[2] => qty = 1
)
[15305] => Array
(
[0] => 15305
[1] => itemX
[2] => qty = 2
)
}
所以因为 qty = 1 是相同的,所以它被过滤掉了,当我需要的是..
Array
(
[15304] => Array
(
[0] => 15304
[1] => Array
(
[0]item1
[1]item2
)
[2] => Array
(
[0]qty = 1
[1]qty = 1
)
)
[15305] => Array
(
[0] => 15305
[1] => itemX
[2] => qty = 2
)
}
如何从 "remove duplicates" 部分中排除某些元素,以便它们像上一个示例一样在内部数组中重复?这是必需的,因为它们直接链接到具有内部数组的其他项目,因此如果例如 item1 内部数组现在有 6 个项目,那么 qty 现在也需要在内部数组中包含所有 6 个项目,即使它们是相同的。
您当前的代码适用于两种情况:
- 正在读取所有数据原样,无需修改
- 读取所有数据并执行通用修改
由于您需要的是条件修改,因此您最好手动创建数组的结构。这样做会增加另一个好处:代码清晰度。您应该始终争取描述性代码,因此使用描述性关联键构建数组将使代码的意图更加清晰。
基于示例数据的建议解决方案(您应该根据自己的特定需求定制的粗略草图):
function readCSV($csvFile)
{
$output = [];
$fileHandle = fopen($csvFile, 'r');
$header = fgetcsv($fileHandle);
while (!feof($fileHandle)) {
$fileRow = fgetcsv($fileHandle, 1024);
$orderId = $fileRow[0];
// skip this row if it's empty (the first field contains no id)
if (empty($orderId)) {
continue;
}
/*
$fileRow[3] is "Buyer name", the first field that's present in one type of row
(the one containing common properties of the order). By checking if it's empty,
we identify the contents of the row - not empty means order row with common
properties, empty means item row with specific item properties.
*/
if (!empty($fileRow[3])) {
// no need to repeat the id inside the array - it's already stored in the key
$output[$orderId] = [
'order_number' => $fileRow[1],
'buyer_username' => $fileRow[2],
'buyer_name' => $fileRow[3],
// here you can continue explicitly adding any property you need
];
} else {
// add a new item entry
$output[$orderId]['items'][] = [
'item_number' => $fileRow[20],
'item_title' => $fileRow[21],
'quantity' => $fileRow[24],
'price' => $fileRow[25],
// here you can continue explicitly adding any property you need
];
}
}
fclose($fileHandle);
return $output;
}
现在,您订单中的所有商品都整齐地存储为子数组,每个子数组仅包含该商品的特定数据,这使得迭代变得非常容易:
foreach($orders[$orderId]['items'] as $item)
我将具有相同集合内部数组名称的数组合并在一起,将键值更改为订单号,然后为未与此代码重复的项目创建更多内部数组...
function readCSV($csvFile)
{
$line_of_text = [];
$file_handle = fopen($csvFile, 'r');
//skip csv headers
//fgetcsv($file_handle);
//fgetcsv($file_handle);
fgetcsv($file_handle);
while (!feof($file_handle)) {
$tmp = fgetcsv($file_handle, 1024);
if (isset($line_of_text[$tmp[0]])) {
foreach ($tmp as $k => $v) {
if (array_key_exists($k, $line_of_text[$tmp[0]])) {
if (!is_array($line_of_text[$tmp[0]][$k])) {
$kVal = $line_of_text[$tmp[0]][$k];
$line_of_text[$tmp[0]][$k] = [];
$line_of_text[$tmp[0]][$k][] = $kVal;
}
$line_of_text[$tmp[0]][$k][] = $v;
$line_of_text[$tmp[0]][$k] = array_unique($line_of_text[$tmp[0]][$k]);
$line_of_text[$tmp[0]][$k] = array_filter($line_of_text[$tmp[0]][$k]);
if (count($line_of_text[$tmp[0]][$k]) == 1) {
$line_of_text[$tmp[0]][$k] = array_values($line_of_text[$tmp[0]][$k]);
$line_of_text[$tmp[0]][$k] = $line_of_text[$tmp[0]][$k][0];
}
if (empty($line_of_text[$tmp[0]][$k])) {
$line_of_text[$tmp[0]][$k] = null;
}
} else {
$line_of_text[$tmp[0]][$k] = null;
}
}
$line_of_text[$tmp[0]][0] = $tmp[0];
} else {
$line_of_text[$tmp[0]] = $tmp;
}
}
fclose($file_handle);
return array_filter(array_values($line_of_text));
}
// Set path to CSV file
$csvFile = 'my.csv';
$csv = readCSV($csvFile);
//$csv is your array
foreach($csv as $key => $value){
if(!array_key_exists(@$value[0],$arr)){
$arr[@$value[0]] = [];
}
$arr[@$value[0]] = array_merge($arr[@$value[0]],$value);
}
echo "<pre>";
print_r($arr);
echo '</pre>';
这轮..
Array
(
[0] => Array
(
[0] => 15304
[1] => item1
[2] => qty = 1
)
[1] => Array
(
[0] => 15304
[1] => item2
[2] => qty = 1
)
[2] => Array
(
[0] => 15305
[1] => itemX
[2] => qty = 2
)
}
进入
Array
(
[15304] => Array
(
[0] => 15304
[1] => Array
(
[0]item1
[1]item2
)
[2] => qty = 1
)
[15305] => Array
(
[0] => 15305
[1] => itemX
[2] => qty = 2
)
}
所以因为 qty = 1 是相同的,所以它被过滤掉了,当我需要的是..
Array
(
[15304] => Array
(
[0] => 15304
[1] => Array
(
[0]item1
[1]item2
)
[2] => Array
(
[0]qty = 1
[1]qty = 1
)
)
[15305] => Array
(
[0] => 15305
[1] => itemX
[2] => qty = 2
)
}
如何从 "remove duplicates" 部分中排除某些元素,以便它们像上一个示例一样在内部数组中重复?这是必需的,因为它们直接链接到具有内部数组的其他项目,因此如果例如 item1 内部数组现在有 6 个项目,那么 qty 现在也需要在内部数组中包含所有 6 个项目,即使它们是相同的。
您当前的代码适用于两种情况:
- 正在读取所有数据原样,无需修改
- 读取所有数据并执行通用修改
由于您需要的是条件修改,因此您最好手动创建数组的结构。这样做会增加另一个好处:代码清晰度。您应该始终争取描述性代码,因此使用描述性关联键构建数组将使代码的意图更加清晰。
基于示例数据的建议解决方案(您应该根据自己的特定需求定制的粗略草图):
function readCSV($csvFile)
{
$output = [];
$fileHandle = fopen($csvFile, 'r');
$header = fgetcsv($fileHandle);
while (!feof($fileHandle)) {
$fileRow = fgetcsv($fileHandle, 1024);
$orderId = $fileRow[0];
// skip this row if it's empty (the first field contains no id)
if (empty($orderId)) {
continue;
}
/*
$fileRow[3] is "Buyer name", the first field that's present in one type of row
(the one containing common properties of the order). By checking if it's empty,
we identify the contents of the row - not empty means order row with common
properties, empty means item row with specific item properties.
*/
if (!empty($fileRow[3])) {
// no need to repeat the id inside the array - it's already stored in the key
$output[$orderId] = [
'order_number' => $fileRow[1],
'buyer_username' => $fileRow[2],
'buyer_name' => $fileRow[3],
// here you can continue explicitly adding any property you need
];
} else {
// add a new item entry
$output[$orderId]['items'][] = [
'item_number' => $fileRow[20],
'item_title' => $fileRow[21],
'quantity' => $fileRow[24],
'price' => $fileRow[25],
// here you can continue explicitly adding any property you need
];
}
}
fclose($fileHandle);
return $output;
}
现在,您订单中的所有商品都整齐地存储为子数组,每个子数组仅包含该商品的特定数据,这使得迭代变得非常容易:
foreach($orders[$orderId]['items'] as $item)