PHP слияния массивов на основе соответствия значения данного индекса - PullRequest
4 голосов
/ 12 июня 2019

У меня есть два таких массива:

Array1

Array
(
    [0] => Array
        (
            [ID] => 101
            [Code] => 1075
            [Date] => 2012-03-03 17:13:12.433
        )

    [1] => Array
        (
            [ID] => 103
            [Code] => 175
            [Date] => 2012-09-05 20:30:02.217
        )

    [2] => Array
        (
            [ID] => 109
            [Code] => 178
            [Date] => 2012-07-05 20:30:02.217
        )

)

array2

Array
(
    [0] => Array
        (
            [Amount] => 1234
            [ID] => 101
        )

    [1] => Array
        (
            [Amount] => 1342
            [ID] => 103
        )

    [2] => Array
        (
            [Amount] => 0
            [ID] => 0
        )

)

Я использую этот код для объединения их на основе соответствующих значений индекса идентификатора.

      $combined = array();
           foreach ($arr as $arrs) {
                   $comb = array('ID' => $arrs['ID'], 'Code' => $arrs['Code'],'Date' => $arrs['Date'],'Amount' => '');
                   foreach ($arr4 as $arr2) {
                       if ($arr2['ID'] == $arrs['ID']) {
                           $comb['Amount'] = $arr2['Amount'];
                           break;
                       }
                       else {
                        $comb['Amount'] = $arr2['Amount'];
                       }
                   }
               $combined[] = $comb;
           }
echo print_r($combined);

А вот желаемый вывод, который я получаю из этого кода:

Array
(
    [0] => Array
        (
            [ID] => 101
            [Code] => 1075
            [Date] => 2012-03-03 17:13:12.433
            [Amount] => 1234
        )

    [1] => Array
        (
            [ID] => 103
            [Code] => 175
            [Date] => 2012-09-05 20:30:02.217
            [Amount] => 1342
        )

    [2] => Array
        (
            [ID] => 109
            [Code] => 178
            [Date] => 2012-07-05 20:30:02.217
            [Amount] => 0
        )

)

Я хочу оптимизировать код так, чтобы

$comb = array('ID' => $arrs['ID'], 'Code' => $arrs['Code'],'Date' => $arrs['Date'],'Amount' => ''); 

должно генерироваться динамически, а не жестко. И вместо $comb['Amount'] = $arr2['Amount']; я хочу, чтобы код автоматически добавлял все остальные поля в первый массив, где совпадает идентификатор.

Как мне этого добиться?

Ответы [ 4 ]

2 голосов
/ 12 июня 2019

Самое простое решение, чтобы сделать его полностью динамичным, кроме ID, как показано ниже:

$arr2 = array_column($array2, "ID");

$finalArray = array();
foreach($array1 as $arr){
    $key = array_search($arr['ID'], $arr2);
    if($key ===false){
        $key = array_search(0, $arr2);
    }
    unset($array2[$key]['ID']);
    $finalArray[] =     array_merge($arr,$array2[$key]);
}

print_r($finalArray);

Выход: - https://3v4l.org/1sDJs

2 голосов
/ 12 июня 2019

Сначала используйте идентификатор в качестве ключа:

$arr1 = array_column($arr1, null, "ID");
$arr2 = array_column($arr2, null, "ID");

Затем сортируйте ключ (чтобы решить не те же самые оригинальные индексы:

ksort($arr1);
ksort($arr2);

Затем используйте array_map как:

$res = array_map('array_merge', $arr1, $arr2);

Используйте array_values в конце, чтобы игнорировать идентификационные ключи.

И если у вас есть другой массив, содержащий поле идентификатора, вы можете использовать ту же логику - обратите внимание, array_map может получить более двух входных массивов ...

Ссылка: массив_колонок , массив_карт , массив_мердж , ксорт

Живой пример: 3v4l

Отредактировано

Используемый шаблон для исправления проблемы, когда элемент отсутствует:

$keys = array_merge(array_keys($a[0]), array_keys($b[0]));
$template = array_combine($keys, array_fill(0, count($keys), null)); // create array of null for all keys
$a = array_column($a, null, "ID");
$b = array_column($b, null, "ID");
ksort($a);
ksort($b);


$res = array_map(function ($e1, $e2) use ($template){
    if ($e1 && $e2) return array_merge($e1, $e2); // if exist merge
    $e = $e1 ? $e1 : $e2; //get the exist element
    return array_replace ($template, $e); // add it
}, $a, $b);

Обратите внимание, что это решение будет действительным только для 2 массивов - оно может быть обобщено, но я оставлю это вам

Живой пример: 3v4l

1 голос
/ 12 июня 2019
$firstArray = [
    [
        'ID' => 101,
        'Code' => 1075,
        'Date' => '2012-03-03 17:13:12.433',
    ],
    [
        'ID' => 103,
        'Code' => 175,
        'Date' => '2012-09-05 20:30:02.217',
    ],
    [
        'ID' => 109,
        'Code' => 178,
        'Date' => '2012-07-05 20:30:02.217',
    ],
];

$secondArray = [
    [
        'ID' => 101,
        'Amount' => 1234,
    ],
    [
        'ID' => 103,
        'Amount' => 1342,
    ],
    [
        'ID' => 0,
        'Amount' => 0,
    ],
];

class DTO implements \Serializable
{
    /** @var int */
    private $id;

    /** @var int */
    private $code;

    /** @var string */
    private $date;

    /** @var int */
    private $amount = 0;

    /**
     * {@inheritDoc}
     */
    public function serialize()
    {
        return [
            'ID' => $this->id,
            'Code' => $this->code,
            'Date' => $this->date,
            'Amount' => $this->amount,
        ];
    }

    /**
     * {@inheritDoc}
     *
     * @param array $serialized
     */
    public function unserialize($serialized): self
    {
        $this->id = $serialized['ID'];
        $this->code = $serialized['Code'];
        $this->date = $serialized['Date'];
        $this->amount = $serialized['Amount'] ?? 0;

        return $this;
    }
}

$thirdArray = [];
foreach ($secondArray as $item) {
    $id = $item['ID'];
    unset($item['ID']);
    $thirdArray[$id] = $item;
}

$thirdArrayKeys = array_keys($thirdArray);
foreach ($firstArray as &$item) {
    $id = $item['ID'];
    $dto = new DTO();
    $dto->unserialize($item);
    if (in_array($id, $thirdArrayKeys)) {
        $dto = $dto->unserialize(array_merge($item, $thirdArray[$id]));
    }

    $item = $dto->serialize();
}

http://sandbox.onlinephpfunctions.com/code/ee72a1c89782f4eef25a1143816f237ca6af129c

1 голос
/ 12 июня 2019

Я настраиваю ваш код, чтобы сделать то, что вам нужно, вот полный код, который работал для меня:

<?php

$arr=Array(
     Array("ID" => 101, "Code" => 1075, "Date" => "2012-03-03 17:13:12.433"),
    Array("ID" => 103, "Code" => 175, "Date" => "2013-03-03 17:13:12.433"),
    Array("ID" => 109, "Code" => 178, "Date" => "2014-03-03 17:13:12.433")
);

$arr4 = Array(
    Array("ID" => 101, "Amount" => 1234),
    Array("ID" => 103, "Amount" => 1342),
    Array("ID" => 0, "Amount" => 0)
);

$combined = array();

foreach ($arr as $i => $arrs) {
    $combined['ID'][$i] = $arrs['ID'];
    $combined['Code'][$i] = $arrs['Code'];
    $combined['Date'][$i] = $arrs['Date'];

    foreach ($arr4 as $arr2) {
        if ($arr2['ID'] == $arrs['ID']) {
            $combined['Amount'][$i] = $arr2['Amount'];
            break;
        }
    }

    if (!isset($combined['Amount'][$i])) {
        $combined['Amount'][] = 0;
    }

}

echo print_r($combined);

?>

Если вам нужны дальнейшие манипуляции по разным причинам, я предлагаю вам прочитать о array_keys иarray_values методы, которые очень полезны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...