2017-08-31 10 views
-1

J'ai deux tableaux avec les mêmes clés à partir de deux requêtes différentes.Comment fusionner deux tableaux en utilisant des valeurs de colonne et trouver la somme des valeurs d'une autre colonne?

Premier résultat de requête:

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

Deuxième résultat de la requête:

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

Le premier tableau peut être vide et/ou le second peut être vide.

Je veux obtenir la création d'un nouveau tableau qui trouve la somme des Contribution valeurs où P_Name valeurs correspondent, comme ceci:

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

J'ai essayé array_merge():

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

$merged_result contient :

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

pourriez-vous montrer vos essais jusqu'à présent? – hassan

+0

Si vos deux tableaux ont la même longueur, vous pouvez facilement les boucler et vérifier avec P_Name, si cela correspond à la somme des contributions et les stocker dans un autre tableau comme résultat –

+0

J'ai essayé Array_merge, $ result1 = $ this-> model1- > getOthersTotal ($ date); $ result2 = $ this-> model1-> getMiscTotal ($ date); $ merged_result = array_merge ($ result1, $ result2); Tableau ( [0] => Tableau ( [Contribution] => 1000,00 [p_name] => A ) [1] => Tableau ( [Contribution] => 1001,00 [p_name] = > A ) [2] => Tableau ( [Contribution] => 69.00 [P_Name] => B ) ) – user3615287

Répondre

0

Voici une manière rapide et sale de le faire: Boucle sur les deux tableaux, la boucle externe remplit la boucle intérieure. Si aucune correspondance n'a été trouvée, $ x remonte à 0 et la valeur sera ajoutée à la boucle interne. Si une correspondance est trouvée, $ x est 1 et la boucle interne se casse pour continuer la boucle externe.

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

Sortie

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

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

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

) 
+0

$ a peut être vide, dans ce cas la sortie sera différente. – user3615287

+0

Si $ a est vide, vous n'avez pas besoin de boucler, car $ b est la réponse. Comme indiqué: c'est une méthode rapide et sale, cela fonctionne, mais il n'y a pas de vérification de vide, etc. – Jeffrey

+0

Pour la personne qui downvote, fournissez une raison (!). Ce code fonctionne, les comportements sont demandés et c'est le code le plus optimisé que je puisse penser. – Jeffrey

0

peu différente approche

$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); 

sortie:

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

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

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

Vous pouvez utiliser array_reduce(), array_map() et 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); 

Remarque En raison de l'utilisation variadics, un certain nombre de tableaux peuvent être transmis à merge(). Nécessite au moins PHP 5.6, cependant.

Pour référence, voir:

Pour un exemple, voir:

+0

Nice générique ... va essayer – user3615287

0

Entrée:

$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']]; 

Si vous attribuez temporairement les clés associatives aux sous-tableaux à l'aide array_column(), vous peut tirer parti array_merge_recursive() pour grouper sur P_Name valeurs, puis appelez array_sum() pour faire l'ajout s'il y a plus d'une valeur à P_Name.

Méthode n ° 1: (Demo)

$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); 

Ou tout simplement faire une fusion standard pour créer un tableau, puis boucle et ajouter que vous allez. Finalisez le tableau de sortie avec array_values() pour réindexer les éléments.

Méthode 2: (Demo)

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

Sortie: (à partir de deux méthodes)

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', 
), 
) 

Il est hors de portée de cette question, mais les chances sont la meilleure approche serait d'effectuer ce regroupement/addition via une requête de base de données.

+0

Great ... Travailler au besoin ... – user3615287

+0

@mickmackusa Si vous "croyez" votre code est le plus efficace, s'il vous plaît fournir un benchtest. [Laissez-moi vous aider avec ça] (https://pastebin.com/B2MnfCyx) et [résultats] (https://pastebin.com/88FdfDbV). Votre méthode est plus de deux fois plus lente que la mienne. Toutes les méthodes sur cette page sont incluses et fournissent la réponse correcte (et attendue). – Jeffrey

+0

Tout point de référence fait à ce stade sera spéculatif car nous ne connaissons pas les tailles de tableau potentiel de l'OP ni la version php de l'OP. Mais bon sur vous pour fournir les retours anticipés, c'est un bon ajout. L'OP devrait certainement vérifier les tableaux vides comme raccourci. Peut-être que je reformulerai ma demande et que je n'hésiterai pas à dire les méthodes les plus concises. – mickmackusa