对两个数组中的项进行分组和求和

时间:2015-11-26 21:46:53

标签: php arrays foreach

我循环遍历两个存储过程的结果集,根据两个过程中的字段获取最终结果。

以下是两个结果集:

- 获取包含或不包含数据的所有$customers

| id |   name  | parentID | calls | duration |  type | 
+----+---------+----------+-------+----------+-------+
|  8 | Telekom |    80    |  100  |   3000   | 01-02 |  
|  8 | Telekom |    80    |   10  |    700   |   080 |
|  8 | Telekom |    80    |    5  |    100   |    05 |
| 16 |  Orange |     7    |   50  |   2200   |    03 |
| 16 |  Orange |     7    | NULL  |   NULL   |  NULL |
|  9 | Verizon |     2    | NULL  |   NULL   |  NULL |  
| 18 |   T&T   |    108   |   30  |   1200   |    04 |  
| 20 |  Sprint |    33    |  120  |   4000   |    09 | 
| 20 |  Sprint |    33    |   60  |   3500   | 01-02 |
| 17 | CellCom |    99    | NULL  |   NULL   |  NULL | 
|  1 | T-Mobile|    14    |   85  |   2600   |   087 | 
|  1 | T-Mobile|    14    |    2  |     30   |    07 |
| 34 | US-Cell |    27    |  240  |   1700   |   084 | 

- 获取所有$subcustomers数据

| id |      name     | parentID | calls | duration |  type | 
+----+---------------+----------+-------+----------+-------+
| 44 |     CallMe    |     8    |   20  |   400    | 01-02 |
| 44 |     CallMe    |     8    |    5  |    20    |   080 |
| 44 |     CallMe    |     8    |   15  |   200    |   087 |
| 72 |    DialNow    |    16    |  100  |  2000    |    03 |
| 72 |    DialNow    |    16    |    5  |   100    |    04 |
| 13 |    Online4U   |     9    |   10  |    25    |    05 |
| 22 | TeleSolutions |     9    |   30  |   200    |    05 |
|  4 |    FonezInc   |     9    |    5  |     5    |   084 |
| 10 |      Digi     |    20    |  100  |  4000    |    09 |
| 11 |    Vodafone   |    20    |   40  |  2400    |    08 |

所需的结果应如下所示:

- 将所有子客户的调用/持续时间添加到客户(如果是subustomer.parentID = customer.id),而不是正确的type,否则向客户显示数据。
  - 如果客户没有呼叫/类型(NULL)并且具有调用的子客户端,请将这些添加到客户。
  - 如果子客户有不同类型的呼叫,也可以将这些添加到客户中   - 类型是动态的,我们现在不会有什么/有多少类型 如下所示:

| id |   name  | parentID | calls | duration |  type | 
+----+---------+----------+-------+----------+-------+
|  8 | Telekom |    80    |  120  |    3400  | 01-02 |
|  8 | Telekom |    80    |   15  |     720  |   080 |
|  8 | Telekom |    80    |    5  |     100  |    05 |
|  8 | Telekom |    80    |   15  |     200  |   087 |
| 16 |  Orange |     7    |  150  |    4200  |    03 |
| 16 |  Orange |     7    |    5  |     100  |    04 |
|  9 | Verizon |     2    |   40  |     225  |    05 |
|  9 | Verizon |     2    |    5  |       5  |   084 |
| 18 |   T&T   |    108   |   30  |    1200  |    04 |
| 20 |  Sprint |    33    |  220  |    4000  |    09 |
| 20 |  Sprint |    33    |   60  |    3500  | 01-02 |
| 20 |  Sprint |    33    |   40  |    2400  |    08 |
|  1 | T-Mobile|    14    |   85  |   2600   |   087 | 
|  1 | T-Mobile|    14    |    2  |     30   |    07 |
| 34 | US-Cell |    27    |  240  |   1700   |   084 |

一个想法是将subcustomerscustomers分组为临时关联数组,其中parentIDID为关键字。之后我们可以建立结果。

输入1 Here's some dummy data用于临时 subustomers 数组。
此数组包含按parentId(第一级)和呼叫类型(第二级)分组的呼叫。它具有以下结构:

[parentID] => Array
    (
        [type] => Array  // e.g. type = 03
            (
                [calls] => value  //calls of type 03
                [duration] => value  //duration of type 03
            )
        [type] => Array //e.g. type = 087
            (
                [calls] => value  //calls of type 087
                [duration] => value  //duration of type 087
            )
         ...
    )

以下是创建临时的代码。 subustomers数组:

$tempS = array();

foreach($subcustomers as $subcustomer) {
    $parentId = $subcustomer['parentID'];
    $calls    = $subcustomer['calls'];
    $type     = $subcustomer['type'];
    $duration = $subcustomer['duration'];

    //if id/type is insered yet
    if(array_key_exists($parentId, $tempS) && array_key_exists($type, $tempS[$parentId])) {
        $tempS[$parentId][$type]['calls'] += $calls;
        $tempS[$parentId][$type]['duration'] += $duration;
    } else {
        $tempS[$parentId][$type]['calls'] = $calls;
        $tempS[$parentId][$type]['duration'] = $duration;
    }    
}


输入2 Here's dummy data表示临时。 客户阵列。该数组的结构如下:

[id] => Array    
    (
        [name] => 'Telekom'
        [parentID] => 80
        [calls] => Array
            (
                [type] => // e.g. calls of type 01-02
                [type] => // e.g. calls of type 05
            )
        [duration] => Array
            (
                [type] => //duration of type 01-02
                [type] => //duration of type 05
            )
    )

这是temp的代码。客户数组:

$tempC = array();

foreach($customers as $customer) {
    $id       = $customer['id'];
    $name     = $customer['name'];
    $parentId = $customer['parentID'];
    $calls    = $customer['calls'];
    $type     = $customer['type'];
    $duration = $customer['duration'];

    //if id/type is insered yet
    if(array_key_exists($id, $tempC) && array_key_exists($type, $tempC[$id])) {
            $tempC[$id]['calls'][$type] += $calls;
            $tempC[$id]['duration'][$type] += $duration;
        } else {
            //if subcustomer has calls of that type
            if(array_key_exists($customerId, $tempS) && array_key_exists($type, $tempS[$customerId])) {
                $tempC[$id]['calls'][$type] = $tempS[$id][$type] + $calls;
                $tempC[$id]['duration'][$type] = $tempS[$id][$type] + $duration;
            } else {
                $tempC[$id]['calls'][$type] = $calls;
                $tempC[$id]['duration'][$type] = $duration;
            }
        $tempC[$id]['name'] = $name;
        $tempC[$id]['parentID'] = $parentId;
    }
}

有这两个临时。数组我们应该计算结果数组。

输出应具有以下相同的结构:

Array
(
    [0] => Array  //indexes should be incremented, starting from 0
        (
            [name] => Telekom
            [label] => 01-02  //label = type
            [count] => 120
            [mins] => 3400
            [customerid] => 8
        )

    [1] => Array
        (
            [name] => Telekom
            [label] => 080
            [count] => 15
            [mins] => 720  // mins = (duration / 60)
            [customerid] => 8
        )
    [2] => Array
        (
            [name] => Telekom
            [label] => 05
            [count] => 5
            [mins] => 100
            [customerid] => 8
        )
    [3] => Array
        (
            [name] => Telekom
            [label] => 087
            [count] => 15
            [mins] => 200
            [customerid] => 8
        )


    [4] => Array
        (
            [name] => Orange
            [label] => 03
            [count] => 150
            [mins] => 4200
            [customerid] => 16
        )

    [5] => Array
        (
            [name] => Orange
            [label] => 04
            [count] => 5
            [mins] => 100
            [customerid] => 16
        )
    ....

)

我试过了:

$result = array();

foreach($tempC as $id => $customer) {

        $type = key($customer['calls']); // ??
        $calls = 0;
        $duration = 0;

        //sums calls of customer
        if(array_key_exists('calls', $customer) && array_key_exists($type, $customer['calls'])) {
            $calls += $customer['calls'][$type];
            $duration += $customer['duration'][$type];
        }
        //sums calls of subcustomer
        if(array_key_exists($id, $tempS) && array_key_exists($type, $tempS[$id])) {
            $calls += $tempS[$id][$type]['calls'];
            $duration += $tempS[$id][$type]['duration'];
        }
        //if there are calls, put in the result array
        if($calls>0) {
            $result[] = [
                'name' => $customer['name'],
                'label' => $type,
                'count' => $calls,
                'mins' => ceil($duration/ 60),
                'customerid' => $id
            ];
        }
}

但上面获取最终结果数组的代码在某处并不正确,因为它没有正确添加所有调用和类型。

注意:这篇文章是在用户@Lipsyor的帮助下创建的。

1 个答案:

答案 0 :(得分:1)

您可以在创建临时数组时收集数组$types中的类型。

首先声明数组:

$types = array();
每个forach(...) $customers$subcustomers插入

$types[$type] = true;

请注意,我使用数组的键来存储类型名称:使用此技巧,您永远不会在数组中插入重复项。

这里是创建结果数组的代码:

$result = array();

foreach($tempC as $id => $customer) {

    foreach ($types as $type => $value) {

        $call = 0;
        $duration = 0;

        if(array_key_exists('calls', $customer) && array_key_exists($type, $customer['calls'])) {
            $call += $customer['calls'][$type];
            $duration += $customer['duration'][$type];
        }
        if(array_key_exists($id, $tempS) && array_key_exists($type, $tempS[$id])) {
            $call += $tempS[$id][$type]['calls'];
            $duration += $tempS[$id][$type]['duration'];
        }
        if($call>0) {
            $result[] = [
                'name' => $customer['name'],
                'label' => $type,
                'count' => $call,
                'mins' => ceil($duration / 60),
                'customerid' => $id
            ];
        }   
    }   
}