1

I have multi-dimensional array:

$array = array(
array(
"id" => 1,
"value" => 100
),
array(
"id" => 1,
"value" => 200
),
array(
"id" => 1,
"value" => 300
),
array(
"id" => 2,
"value" => 2
),
array(
"id" => 2,
"value" => 5
),
array(
"id" => 3,
"value" => 10.50
),
);

I need to get new multi-dimensional array, like this:

$newArray = array(
array(
"id" => "1",
"sum_of_values" => 600
),
array(
"id" => 2,
"sum_of_values" => 7
),
array(
"id" => 3,
"sum_of_values" => 10.50
),
);

I mean, key [sum_of_values] should counts values in sub-arrays with the same key [id].

I've tried this:

$cnt = count($array);

            $finalArray = array();
            $tempArray = array();
            for($i = 0; $i < $cnt; $i++){
                if($array[$i]["id"] == $array[$i++]["id"]){

                    $search = $array[$i]["id"];
                    $column = "value";

                    $sum = array_sum(
                                    array_map(
                                        function($data) use ($column) {
                                            return $data[$column];
                                        },
                                    array_filter(
                                        $array,
                                        function($data) use ($search) {
                                            return fnmatch($search, $data["id"]);
                                        }
                                    )
                                    )
                    );

                    $tempArray = array(
                        "id" => $array[$i]["id"],
                        "sum_of_values" => $sum
                        );

                    $finalArray[] = $tempArray;

                    } else {
                        $tempArray = array(
                            "id" => $array[$i]["id"],
                            "sum_of_values" => $array[$i]["value"]
                            );
                        }
            }

And it works, it counts values of sub-arrays with same [id]. But the problem is not returning sub-arrays, key [id] of which doesn't have same examples. In my case - sub-array with [id] = 3 will not return. Also, sub-arrays with [id] = 1 and [id] = 2 will repeat [n-n/2] times.

I think, that problem is in using cycle - for ($i = 0; $i < $cnt; $i++) and condition if ($array[$i]["id"] == $array[$i++]["id"]), because it looks stupid, but i can't find anything else.

2 Answers 2

3

Your function seems too complicated. How about this?

$result = array();
foreach ($array as $item) {
    if (!empty($result[$item['id']]))
        $result[$item['id']]['sum_of_values'] += $item['value'];
    else
        $result[$item['id']] = array(
            'id' => $item['id'],
            'sum_of_values' => $item['value']
        );
}

If you print_r($result) you get:

 Array
(
    [1] => Array
        (
            [id] => 1
            [sum_of_values] => 600
        )

    [2] => Array
        (
            [id] => 2
            [sum_of_values] => 7
        )

    [3] => Array
        (
            [id] => 3
            [sum_of_values] => 10.5
        )

)
Sign up to request clarification or add additional context in comments.

1 Comment

this is exactly what i needed! thanks for help. need to analise this example for future
1

Just as an alternative: this is a sitter for array_reduce():

$totals = array_reduce($array, function($reduction, $current){
    $id = $current["id"];
    if (empty($reduction[$id])){
        $reduction[$id] = ["id"=>$id, "sum_of_values"=>0];
    }
    $reduction[$id]["sum_of_values"] += $current["value"];
    return $reduction;
}, []);

I prefer this sort of approach to generic looping/processing: I think it's a bit cleaner. But mileage varies, obviously.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.