首页 > 解决方案 > PHP数组合并,忽略某些重复的键,让它们包含在内部创建的数组中

问题描述

我将具有相同集合内部数组名称的数组合并在一起,将键值更改为订单号,然后为不与此代码重复的项目创建更多内部数组......

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
        )
}

如何从“删除重复项”部分中排除某些部分,以便它们在内部数组中重复,就像我上一个示例中一样?这是必需的,因为它们直接链接到具有内部数组的其他项目,因此,例如,如果 item1 内部数组现在有 6 个项目,则 qty 现在需要在内部数组中也有所有 6 个项目,即使它们是相同的。

标签: phparraysassociative-arrayarray-merge

解决方案


您当前的代码适用于两种情况:

  1. 按原样读取所有数据,无需修改
  2. 读取所有数据并执行通用修改

由于您需要的是条件修改,因此您最好手动创建数组的结构。这样做会增加另一个好处:代码清晰。您应该始终争取描述性代码,因此使用描述性关联键构建数组将使代码的意图更清晰。

根据示例数据提出的解决方案(您应该根据您的特定需求定制的粗略草图):

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)

推荐阅读