问题
I have an array of the products as in the sample below. Products can be two, or three and more. In this example, three.
$all_products = array(
    'product_1'       =>array(
        'price'       =>'$100',
        'quantity'    =>'2pcs.',
        'availability'=>'In Stock',
        'manufacturer'=>'Apple'),
    'product_2'       =>array(
        'price'       =>'$200',
        'quantity'    =>'2pcs.',
        'availability'=>'In Stock',
        'manufacturer'=>''),
    'product_3'       =>array(
        'price'       =>'$300',
        'quantity'    =>'2pcs.',
        'availability'=>'In Stock',
        'manufacturer'=>'')
);
I need to compare values of the products by each key. To highlight rows in the compare table where price, quantity, availability, or manufacturer is different.
I have tried this function to check which values are different and return one temp array:
function compare_array($array, $key) {
    $temp_array = array();
    $i = 0;
    $key_array = array();
    foreach($array as $val) {
        if (isset($val[$key])) {
            if (!in_array($val[$key], $key_array)) {
                $key_array[$i] = $val[$key];
                $temp_array[$i] = $val;
            } 
        }
        $i++;
    }
    return $temp_array;
}   
and then:
foreach ($all_products as $products) {
    foreach ($products as $product_key => $val) {
        foreach ($this->compare_array($all_products, $product_key) as $temp_value) { 
            if ($val != $temp_value) {
                $style[$product_key] = 'style="background-color: lightblue;"';//style for highlight    
            }
        }
    } 
}
Problem is when some value in array is empty. Like in this example, manufacturer.
Maybe someone has more light solution?
回答1:
I need compare values of the products by each key. To highlight rows in the compare table where price, quantity, availability, or manufacturer is different.
If you want to highlight all products unless all of them have exactly the same price, quantity, availability, or manufacturer.
function:
function productsIdentical(array &$products) : bool
{
    if (count($products) < 2) {
        throw new \InvalidArgumentException("You should pass at least 2 products to compare");
    }
    $compare = '';
    foreach ($products as $product) {
        ksort($product); //to make comparison of key order insensitive
        $sha = sha1(json_encode($product));
        if (empty($compare)) {
            $compare = $sha;
        } elseif ($sha !== $compare) {
            return false;
        }
    }
    return true;
}
returns true only if all products' fields have exactly the same keys and value, otherwise it returns false
so you use it this way:
$identicalFlag = productsIdentical($all_products);
if ($identicalFlag === false) {
    echo "Products are not identical:" . PHP_EOL;
    $nonIdenticalProductsArr = array_keys($all_products);
    echo "Non identical products are:" . PHP_EOL;
    print_r($nonIdenticalProductsArr);
    //do your styling  on $nonIdenticalProducts
} else {
    echo "Products are identical" . PHP_EOL;
}
Output:
for identical products:
Products are identical
for non identical:
Products are not identical:
Non identical products are:
Array
(
    [0] => product_1
    [1] => product_2
    [2] => product_3
)
Or if you want to detect every product field that is not the same across all products in the array use this function:
function getFieldsNonIdentical(array &$products) : array
{
    if (count($products) < 2) {
        throw new \InvalidArgumentException("You should pass at least 2 products to compare");
    }
    $compareArr = [];
    $keyDifferentArr = [];
    foreach ($products as $product) {
        foreach($product as $key => $val) {
            if (!key_exists($key, $compareArr)) {
                $compareArr[$key] = $val;
            } elseif ($compareArr[$key] !== $val) {
                $keyDifferentArr[$key] = true;
            }
        }
    }
    return array_keys($keyDifferentArr);
}
this way:
$fieldsNonIdentical = getFieldsNonIdentical($all_products);
if (!empty($fieldsNonIdentical)) {
    echo "Fields that are non identical:" . PHP_EOL;
    print_r($fieldsNonIdentical);
    //do your styling
    $nonIdenticalStyle = 'style="background-color: lightblue;"';
    $styleArr = [];
    foreach ($fieldsNonIdentical as $key => $value) {
        $styleArr[$value] = $nonIdenticalStyle;
    }
    echo "Non Identical fields styling is:" . PHP_EOL;
    print_r($styleArr);
} else {
    echo "All fields in all products are the same." . PHP_EOL;
}
Output
for identical:
All fields in all products are the same.
for non identical:
Fields that are non identical:
Array
(
    [0] => price
    [1] => manufacturer
)
Non Identical fields styling is:
Array
(
    [price] => style="background-color: lightblue;"
    [manufacturer] => style="background-color: lightblue;"
)
来源:https://stackoverflow.com/questions/58809613/compare-multidimensional-array-values-by-key-in-php