Viewed   101 times

just a simple problem here. I have the following array:

Array(21) {
[0] => Array(7) {
    ["punti"] => Integer  418
    ["vittorie"] => Integer  9
    ["podi"] => Integer  18
    ["gv"] => Integer  14
    ["id_pilota"] => Integer  1
    ["team"] => String(15) "Red Bull Racing"
    ["naz"] => String(2) "it"
}
[1] => Array(7) {
    ["punti"] => Integer  353
    ["vittorie"] => Integer  6
    ["podi"] => Integer  16
    ["gv"] => Integer  3
    ["id_pilota"] => Integer  19
    ["team"] => String(16) "Scuderia Ferrari"
    ["naz"] => String(2) "it"
}
[2] => Array(7) {
    ["punti"] => Integer  335
    ["vittorie"] => Integer  4
    ["podi"] => Integer  15
    ["gv"] => Integer  1
    ["id_pilota"] => Integer  5
    ["team"] => String(12) "Mercedes-AMG"
    ["naz"] => String(2) "it"
}
[3] => Array(7) {
    ["punti"] => Integer  181
    ["vittorie"] => Integer  1
    ["podi"] => Integer  5
    ["gv"] => Integer  1
    ["id_pilota"] => Integer  2
    ["team"] => String(12) "Mercedes-AMG"
    ["naz"] => String(2) "it"
}
[4] => Array(7) {
    ["punti"] => Integer  147
    ["vittorie"] => Integer  0
    ["podi"] => Integer  3
    ["gv"] => Integer  0
    ["id_pilota"] => Integer  14
    ["team"] => String(15) "Racing Point F1"
    ["naz"] => String(2) "mx"
}
[5] => Array(7) {
    ["punti"] => Integer  127
    ["vittorie"] => Integer  0
    ["podi"] => Integer  0
    ["gv"] => Integer  0
    ["id_pilota"] => Integer  13
    ["team"] => String(7) "Haas F1"
    ["naz"] => String(2) "dk"
}

which goes down to 21 elements.

My goal is to sum up all the points ("punti" indexes), based on each pilot's team. So to obtain something like this:

Array(10) {
[0] => Array(2) {
    ["team"] => String(...) "Mercedes-AMG")
    ["points"] => Integer  516

I know this is quite easy, but what is the quickest / most convenient way to solve such problem?

 Answers

4

You need to iterate over your results, adding a new entry to the output when you encounter a new team, or updating the points value when you find the same team again. This is most easily done by initially indexing the output by the team name, and then using array_values to re-index the array numerically:

$teams = array();
foreach ($results as $result) {
    $team = $result['team'];
    if (!isset($teams[$team])) {
        $teams[$team] = array('team' => $team, 'points' => $result['punti']);
    }
    else {
        $teams[$team]['points'] += $result['punti'];
    }
}
$teams = array_values($teams);
print_r($teams);

Output (for your sample data):

Array
(
    [0] => Array
        (
            [team] => Red Bull Racing
            [points] => 418
        )
    [1] => Array
        (
            [team] => Scuderia Ferrari
            [points] => 353
        )
    [2] => Array
        (
            [team] => Mercedes-AMG
            [points] => 516
        )
    [3] => Array
        (
            [team] => Racing Point F1
            [points] => 147
        )
    [4] => Array
        (
            [team] => Haas F1
            [points] => 127
        )
)

Demo on 3v4l.org

Friday, August 12, 2022
 
5

This function should replace all instances of $oldKey with $newKey.

function replaceKey($subject, $newKey, $oldKey) {

    // if the value is not an array, then you have reached the deepest 
    // point of the branch, so return the value
    if (!is_array($subject)) return $subject;

    $newArray = array(); // empty array to hold copy of subject
    foreach ($subject as $key => $value) {

        // replace the key with the new key only if it is the old key
        $key = ($key === $oldKey) ? $newKey : $key;

        // add the value with the recursive call
        $newArray[$key] = replaceKey($value, $newKey, $oldKey);
    }
    return $newArray;
}
Sunday, November 20, 2022
 
ab91
 
2

This should work for arrays like the one of your example ($arr is an array like the one in your example, I haven't defined it here for simplicity's sake):

$res = array();
foreach($arr as $value) {
    foreach($value as $key => $number) {
        (!isset($res[$key])) ?
            $res[$key] = $number :
            $res[$key] += $number;
    }
}

print_r($res);
Friday, September 30, 2022
 
3

not pretty but heres how I would do it with a nested foreach;

$aStartingArray = array();
$aStartingArray[] = array('source'=>'ABC', 'target' => 'DEF', 'total_volume' => 10); 
$aStartingArray[] = array('source'=>'ABC', 'target' => 'GHI', 'total_volume' => 5); 
$aStartingArray[] = array('source'=>'ABC', 'target' => 'DEF', 'total_volume' => 5); 


$aSortedArray = array();

foreach ($aStartingArray as $aArray) {

    $bSet = false;

    foreach ($aSortedArray as $iPos => $aTempSortedArray) {

        if(
            $aTempSortedArray['source'] == $aArray['source'] && 
            $aTempSortedArray['target'] == $aArray['target']){

            $aSortedArray[$iPos]['total_volume'] += $aArray['total_volume'];

            $bSet = true;
        }

    }

    if(!$bSet) {

        $aSortedArray[] = array(
            'source' => $aArray['source'], 
            'target' => $aArray['target'], 
            'total_volume' => $aArray['total_volume']
            );
    }
}


var_dump($aSortedArray);
Thursday, September 29, 2022
 
2

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;"
)
Wednesday, December 7, 2022
 
sparr
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :