Как объединить два массива, используя значения столбцов и найти сумму значений другого столбца?

У меня есть два массива с одинаковыми ключами из двух разных запросов.

Результат первого запроса:

Array
(
[0] => Array
(
[Contribution] => 1000.00
[P_Name] => A
)
[1] => Array
(
[Contribution] => 1500.00
[P_Name] => B
)
)

Результат второго запроса:

Array
(
[0] => Array
(
[Contribution] => 100.00
[P_Name] => A
)
[1] => Array
(
[Contribution] => 200.00
[P_Name] => B
)
)

Первый массив может быть пустым и / или второй может быть пустым.

Я хочу получить новый массив, который находит сумму Contribution значения где P_Name значения совпадают, вот так:

Array
(
[0] => Array
(
[Contribution] => 1100.00
[P_Name] => A
)
[1] => Array
(
[Contribution] => 1700.00
[P_Name] => B
)
)

я пытался array_merge():

$result1= $this->model1->getOthersTotal($date);
$result2=$this->model1->getMiscTotal($date);
$merged_result = array_merge( $result1, $result2 );

$merged_result содержит:

Array (
[0] => Array (
[Contribution] => 1000.00
[P_Name] => A
)
[1] => Array (
[Contribution] => 1001.00
[P_Name] => A
)
[2] => Array (
[Contribution] => 69.00
[P_Name] => B
)
)

-1

Решение

Вот быстрый и грязный способ сделать это: зациклить оба массива, внешний цикл заполняет внутренний цикл. Если совпадения не найдено, $ x отправляет 0, и значение будет добавлено во внутренний цикл. Если совпадение найдено, $ x равен 1, и внутренний цикл прерывается, чтобы продолжить внешний цикл.

$a = [['a' => 10,'b' => 'g'], ['a' => 11,'b' => 'h']];
$b = [['a' => 1, 'b' => 'g'], ['a' => 2, 'b' => 'h'], ['a' => 3, 'b' => 'i']];

// now its fool proof.
function mergeData( $a, $b )
{
if( empty( $a ) && empty( $b ) )
return [];
if( empty( $a ) )
return $b;
if( empty( $b ) )
return $a;

foreach( $b AS $i => $c ) {
$x = 0;
foreach( $a AS $ii => $d ) {
if( $c['b'] == $d['b'] ) {
$a[ $ii ]['a'] += $c['a'];
$x             = 1;
break;
}
}
if( !$x )
$a[] = $b[ $i ];
}

return $a;
}

Выход

Array
(
[0] => Array
(
[a] => 11
[b] => g
)

[1] => Array
(
[a] => 13
[b] => h
)

[2] => Array
(
[a] => 3
[b] => i
)

)
1

Другие решения

Немного другой подход

$array1 = [
[
'Contribution' => 10,
'P_Name' => 'A'
],
[
'Contribution' => 1500,
'P_Name' => 'B'
]
];
$array2 = [
[
'Contribution' => 200,
'P_Name' => 'B'
],
[
'Contribution' => 100,
'P_Name' => 'C'
],
];

$array3 = array_map(function($elem) use (&$array2){
foreach($array2 as $i => &$a2){
if($a2['P_Name'] == $elem['P_Name']){
$a2['Contribution'] += $elem['Contribution'];
return;
}
}
return $elem;
},$array1);

$array3 = array_merge(array_filter($array3),$array2);

print_r($array3);

выход:

Array
(
[0] => Array
(
[Contribution] => 10
[P_Name] => A
)

[1] => Array
(
[Contribution] => 1700
[P_Name] => B
)

[2] => Array
(
[Contribution] => 100
[P_Name] => C
)
)
0

Ты можешь использовать array_reduce(), array_map(), а также array_sum():

<?php

function merge(array ...$sets)
{
/**
* group contributions by name
*/
$contributions = array_reduce(
$sets,
function (array $contributions, array $set) {
foreach ($set as $element) {
$name = $element['P_Name'];
$contribution = $element['Contribution'];

if (!array_key_exists($name, $contributions)) {
$contributions[$name] = [];
}

$contributions[$name][] = $contribution;

}

return $contributions;
},
[]
);

/**
* normalize the array so we remove the name as key, and return a tuple of name and contribution, with the desired
* structure
*/
return array_values(array_map(function (array $contribution, $name) {
return [
'Contribution' => array_sum($contribution),
'P_Name' => $name,
];
}, $contributions, array_keys($contributions)));
}

$a = [
[
'Contribution' => 1000,
'P_Name' => 'A',
],
[
'Contribution' => 1500,
'P_Name' => 'B',
],
];

$b = [
[
'Contribution' => 100,
'P_Name' => 'A',
],
[
'Contribution' => 200,
'P_Name' => 'B',
],
];

$merged = merge($a, $b);

var_dump($merged);

Заметка Из-за использования variadics любое количество массивов может быть передано merge(), Требуется хотя бы PHP 5.6.

Для справки смотрите:

Например, смотрите:

0

Входные данные:

$a=[['Contribution'=>1000,'P_Name'=>'A'],
['Contribution'=>1500,'P_Name'=>'B'],
['Contribution'=>2000,'P_Name'=>'C']];
$b=[['Contribution'=>100,'P_Name'=>'A'],
['Contribution'=>200,'P_Name'=>'B'],
['Contribution'=>300,'P_Name'=>'D']];

Если вы временно назначаете ассоциативные ключи для подмассивов, используя array_column()тогда вы можете использовать array_merge_recursive() группировать по P_Name значения, затем позвоните array_sum() сделать сложение, если существует более одного значения для данного P_Name,

Способ № 1: (демонстрация)

$keyed=array_merge_recursive(array_column($a,NULL,'P_Name'),array_column($b,NULL,'P_Name'));
foreach($keyed as $p_name=>$array){
$result[]=['Contribution'=>(is_array($array['Contribution'])?array_sum($array['Contribution']):$array['Contribution']),'P_Name'=>$p_name];
}
var_export($result);

Или просто выполните стандартное слияние, чтобы создать один массив, затем зациклите и добавьте по мере необходимости. Завершить выходной массив с array_values() переиндексировать элементы.

Способ № 2: (демонстрация)

foreach(array_merge($a,$b) as $array){
if(isset($result[$array['P_Name']])){
$result[$array['P_Name']]['Contribution']+=$array['Contribution'];
}else{
$result[$array['P_Name']]=$array;
}
}
$result=array_values($result);
var_export($result);

Вывод: (из любого метода)

array (
0 =>
array (
'Contribution' => 1100,
'P_Name' => 'A',
),
1 =>
array (
'Contribution' => 1700,
'P_Name' => 'B',
),
2 =>
array (
'Contribution' => 2000,
'P_Name' => 'C',
),
3 =>
array (
'Contribution' => 300,
'P_Name' => 'D',
),
)

Это выходит за рамки этого вопроса, но, скорее всего, наилучшим подходом будет выполнение этой группировки / добавления с помощью запроса к базе данных.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector