PHP объединение массивов, игнорирование определенных дублированных ключей и включение их во внутренние созданные массивы - PullRequest
0 голосов
/ 07 апреля 2020

Я объединяю массивы с одним и тем же заданным именем внутреннего массива, меняю значение ключа на номер заказа, а затем создаю дополнительные внутренние массивы для элементов, которые не дублируются этим кодом ...

<code>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 '
';

Это превращает ..

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 элементов во внутреннем массиве, даже если они одинаковы.

1 Ответ

1 голос
/ 09 апреля 2020

Ваш текущий код подходит для двух случаев:

  1. Чтение всех данных как есть , без изменений
  2. Чтение всех данных и выполнение универсальной модификации

Поскольку вам нужна условная модификация, кажется, что вам лучше создать структуру массива вручную. Это добавит еще одно преимущество: ясность кода. Вы всегда должны стремиться к описательному коду, поэтому построение массива с описательными ассоциативными ключами сделает смысл кода более понятным.

Предлагаемое решение, основанное на данных примера (грубый набросок, который вы должны адаптировать под свои спецификации c needs):

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

Теперь все элементы вашего заказа аккуратно хранятся в виде подмассивов, каждый из которых содержит только данные, указанные c для этого элемента, что упрощает итерацию:

foreach($orders[$orderId]['items'] as $item)
...