2016-12-02 1 views
3

J'ai 2 tableaux de données provenant de différentes sources de données dans différents formats, mais ils représentent les mêmes ressources. Donc id dans l'un est le même que guid dans l'autre par exemple.PHP array diff types différents

Actuellement, je convertis l'un des tableaux pour qu'il corresponde à l'autre, puis je les exécute via array_udiff pour obtenir la différence.

Cependant, j'ai besoin de comparer 3 propriétés pour vérifier si elles correspondent, donc je ne peux pas retourner -1,0,1 car les 3 champs correspondent ou ne correspondent pas.

Si je retourne simplement -1 ou 0, il fonctionne à comparer $a-$b, mais ne parvient à comparer à $b$a

$arr_a = [['id'=>1, 'a'=>1, 'b'=>0],['id'=>2, 'a'=>2, 'b'=>3],['id'=>3, 'a'=>1, 'b'=>0]]; 
$arr_b = [['id'=>3, 'a'=>1, 'b'=>0],['id'=>4, 'a'=>2, 'b'=>3],['id'=>5, 'a'=>1, 'b'=>0]]; 

function diff($a, $b) { 
    if(($a['id'] == $b['id']) 
     && ($a['a'] == $b['a']) 
     && ($a['b'] == $b['b']) 
    ) { 
    return 0; 
    } else { 
    return -1; 
    } 

$not_in_b = array_udiff($arr_a, $arr_b,'diff'); 
$not_in_a = array_udiff($arr_b, $arr_a,'diff'); 

print_r($not_in_b); 
print_r($not_in_a); 

Les rendements ci-dessus ...

Array 
(
    [0] => Array 
     (
      [id] => 1 
      [a] => 1 
      [b] => 0 
     ) 

    [1] => Array 
     (
      [id] => 2 
      [a] => 2 
      [b] => 3 
     ) 

) 
Array 
(
    [0] => Array 
     (
      [id] => 3 
      [a] => 1 
      [b] => 0 
     ) 

    [1] => Array 
     (
      [id] => 4 
      [a] => 2 
      [b] => 3 
     ) 

    [2] => Array 
     (
      [id] => 5 
      [a] => 1 
      [b] => 0 
     ) 

) 

Comme vous pouvez le voir le diff de $a à $b fonctionne, mais $b à $a ne ...

Comment puis-je comparer plusieurs Vaules comme celui-ci pour l'égalité ...

MISE À JOUR

Cela fonctionne, mais faire deux tableaux avec les trois valeurs de propriétés d'identification comme les clés ...

$arr_a = [['id'=>1, 'a'=>1, 'b'=>0],['id'=>2, 'a'=>2, 'b'=>3],['id'=>3, 'a'=>1, 'b'=>0]]; 
$arr_b = [['id'=>3, 'a'=>1, 'b'=>0],['id'=>4, 'a'=>2, 'b'=>3],['id'=>5, 'a'=>1, 'b'=>0]]; 

$arra_a_keys=[]; 
foreach($arr_a as $item) { 
    $arra_a_keys[$item['id'].'_'.$item['a'].'_'.$item['b']] = $item; 
} 

$arra_b_keys=[]; 
foreach($arr_b as $item) { 
    $arra_b_keys[$item['id'].'_'.$item['a'].'_'.$item['b']] = $item; 
} 

$not_in_b = array_diff_key($arra_a_keys, $arra_b_keys); 
$not_in_a = array_diff_key($arra_b_keys, $arra_a_keys); 

print_r($not_in_b); 
print_r($not_in_a); 
+2

"ne fonctionnent pas". Montrez le code que vous avez essayé de toute façon et décrivez de quelle façon cela ne fonctionne pas. –

+0

Quels sont les éléments qui comparent les critères? seulement 'id' et' guid' devraient correspondre? – sevavietl

+0

@PatrickQ J'ai ajouté un exemple avec plus de détails ... –

Répondre

0

Vous pouvez utiliser un foreach pour le tableau de marque comparable

$ids1 = []; 
    foreach($a as $v1){ 
     $i1[] = $v1['id']; 
    } 
    $ids2 = []; 

    foreach($b as $v2){ 
     $i2[] = $v2['guid']; 
    } 
    $one_notin_two = array_diff($i1,$i2); 
    $two_notin_one = array_diff($i2,$i1); 
1

pour comparer par ID s seulement vous pouvez effectuer les opérations suivantes:

$ids = array_column($a, 'id'); 
$guids = array_column($b, 'guid'); 

$not_in_b = array_filter($a, function ($item) use ($guids) { 
    return !in_array($item['id'], $guids); 
}); 
$not_in_a = array_filter($b, function ($item) use ($ids) { 
    return !in_array($item['guid'], $ids); 
}); 

est ici working demo.

Addition:

En outre, vous pouvez le faire avec array_udiff:

$compareFunction = function ($a, $b) { 
    $id1 = isset($a['id']) ? $a['id'] : $a['guid']; 
    $id2 = isset($b['id']) ? $b['id'] : $b['guid']; 

    return strcmp($id1, $id2); 
}; 

$not_in_b = array_udiff($a, $b, $compareFunction); 
$not_in_a = array_udiff($b, $a, $compareFunction); 

est ici working demo.

Mais sachez que array_udiff n'est vraiment pas la fonction la plus directe. Il n'y a rien à ce sujet dans la documentation, mais il compare non seulement les tableaux que vous avez fournis avec une fonction de rappel, mais les trie également. Voilà pourquoi

La fonction de comparaison doit retourner un entier inférieur, égal ou supérieur à zéro si le premier argument est considéré comme respectivement inférieur, égal ou supérieur au second.

Mais ce tri aussi des tours du programmeur, parce qu'il attend que la fonction int callback (mixed $a, mixed $b)$a vient de $array1 et $b vient de $array2. Ce n'est pas le cas. Vous pouvez lire this article pour plus de détails. Donc, je pense que la solution array_filter est plus compréhensible

0

Vous pouvez résoudre ce problème en utilisant array_column() et array_diff().

Voici un exemple de code: See Live Demo

$a = [['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]]; 
$b = [['guid' => 3], ['guid' => 4], ['guid' => 6], ['guid' => 7]]; 

$a = array_column($a, 'id'); 
$b = array_column($b, 'guid'); 

$not_in_b = array_diff($a, $b); 
$not_in_a = array_diff($b, $a); 

espère qu'il devrait être résolu votre problème. Je vous remercie.