简体   繁体   中英

Best way in comparing multiple values in arrays

if ($item['id_piatto'] === $riga['id_piatto'] && $item['id_portata'] === $riga['id_portata'] && $item['id_dieta'] === $riga['id_dieta']) {
    $item['quantita'] += $riga['quantita'];
} 

Is there a more compact way to compare multiple values of two arrays instead of the one in the code above?

In order to compare several values ​​of two arrays (Not the whole array!) with given keys, such a function is useful:

function array_cmp_keys(array $arr1, array $arr2, array $keys){
  foreach($keys as $key){
    if($arr1[$key] !== $arr2[$key]) return false;
  }
  return true;
}

Testdata:

$item = ['id_piatto' => 1, 'id_portata' => 2, 'id_dieta' => 3, 'xx' => 4];
$riga = ['id_piatto' => 1, 'id_portata' => 2, 'id_dieta' => 3, 'xx' => 5];

How to use:

$keys = ['id_piatto', 'id_portata', 'id_dieta'];

if(array_cmp_keys($item,$riga,$keys)) {
  echo "Equal";
}
else {
  echo "not Equal";
}

"Equal" is output for this test data

As the top comment points out, your original solution is just fine especially if you are only dealing with a small number of array elements. You only have 3 lines of code and the memory footprint is tiny. Go with your own solution unless you have a good reason not to.

If you have a large number of array elements to compare and a limited number of elements to exclude, you may wish to automate things a bit. Note that this has a memory hit because you're duplicating the array.

<?php

// Original arrays
$first = ['name' => 'tony', 'address' => '123 Main St.', 'position' => 'clerk', 'amount' => 15];
$second = ['name' => 'tony', 'address' => '123 Main St.', 'position' => 'clerk', 'amount' => 23];

// Keys that you want to exclude from the comparison. 
$excludeInComparison = ['amount'];

// Duplicate the arrays but exclude these keys for the comparison.
$firstFiltered = array_diff_key($first, array_flip($excludeInComparison));
$secondFiltered = array_diff_key($second, array_flip($excludeInComparison));

// Compare the filtered arrays
if ($firstFiltered == $secondFiltered) {
    $first['amount'] += $second['amount'];
}

You can use PHP's advanced array destructuring syntax , available from PHP 7.1:

['id_piatto' => $a[], 'id_portata' => $a[], 'id_dieta' => $a[]] = $item;
['id_piatto' => $b[], 'id_portata' => $b[], 'id_dieta' => $b[]] = $riga;

$item['quantita'] += ($a === $b) ? $riga['quantita'] : 0;

I think this looks nice and readable, but it really shines when the input arrays have different keys and/or nested structure, I'll give you an example:

$one = [
    'foo' => 1,
    'bar' => [1,2,3],
    'baz' => ['baz_id' => 4]
];
$two = [
    'foo' => 1,
    'bar' => [5,5,3],
    'boo_id' => 4
];

['foo' => $a[], 'bar' => [2 => $a[]], 'baz' => ['baz_id' => $a[]]] = $one;
['foo' => $b[], 'bar' => [2 => $b[]], 'boo_id' => $b[]] = $two;

var_dump($a === $b); // true

Note how I used a numeric index to access the third value in the 'bar' sub-array. Finally, this is much more flexible than the custom function approach in some of the other answers. For detailed info, Check out this blog post about array destructuring in PHP.

Addendum

If it's all about nice looking code and readability, is this really better than the standard approach (maybe structured with some linebreaks)?

if(
        $one['foo'] === $two['foo']
    &&  $one['bar'][2] === $two['bar'][2]
    &&  $one['baz']['baz_id'] === $two['boo_id']
) {
    // Do something...      
}

Apart from the stylistic viewpoint, the standard approach has still two big advantages:

  1. One could easily use an individual comparison operator for each expression

  2. One could implement more advanced boolean logic

One the other hand, the destructuring approach will generate 2 "normalized" subsets of your input arrays on the fly, which could be useful later...

if($a === $b) {
    // Do something
} else {
    return [
        'error_msg' => "Inputs don't match",
        'context' => [
            'expected' => $a,
            'actual' => $b
        ]
    ];
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM