如何基于深层值合并数组?

时间:2017-05-09 12:36:34

标签: php arrays multidimensional-array

Array (
    [0] => Array (
        [OrderProduct] => Array (
            [pro_code] => B1
            [totalQTY] => 4
        )
    )
    [1] => Array (
        [OrderProduct] => Array (
            [pro_code] => B2
            [totalQTY] => 4
        )
    )
    [2] => Array (
        [OrderProduct] => Array (
            [pro_code] => B4
            [totalQTY] => 4
        )
    )
)
Array (
    [0] => Array (
        [OrderProduct] => Array (
            [pro_code] => B1
            [totalDistSalesQTY] => 360
        )
    )
    [1] => Array (
        [OrderProduct] => Array (
            [pro_code] => B2
            [totalDistSalesQTY] => 600
        )
    )
    [2] => Array (
        [OrderProduct] => Array (
            [pro_code] => B3
            [totalDistSalesQTY] => 600
        )
    )
)   

我想在pro_code值上合并上面的两个数组。这是预期的结果:

Array (
    [0] => Array (
        [OrderProduct] => Array (
            [pro_code] => B1
            [totalDistSalesQTY] => 360
            [totalQTY] => 4
        )
    )
    [1] => Array (
        [OrderProduct] => Array (
            [pro_code] => B2
            [totalDistSalesQTY] => 600
            [totalQTY] => 4
        )
    )
    [2] => Array (
        [OrderProduct] => Array (
            [pro_code] => B3
            [totalDistSalesQTY] => 600
        )
    )
    [3] => Array (
        [OrderProduct] => Array (
            [pro_code] => B4
            [totalQTY] => 4
        )
    )
)

我想合并多个数组。请帮我合并一下。我应用了很多技术来合并它。我仍然找不到自己的方式。请帮我解决这个问题。

3 个答案:

答案 0 :(得分:1)

所以基本上,你要做的是在序列上实现merge algorithm。这是基本的编程论文之一,所以不应该太难。

首先,您必须按照一个唯一的,严格可排序的值(这里是pro_code)按升序对序列(示例中的数组)进行排序。

其次,您需要同时迭代这两个序列。 如果当前项唯一键(pro_code)匹配,则合并它们并推送到结果数组,如果没有将具有较小键的那个键推送到结果数组。推后,将推送序列的索引加1。

在到达其中一个序列的末尾后,将其余部分推送到结果数组。

这就是它在php中的实现方式:

<?php

//  Compare func for usort
function compare($a, $b) {
    return strcmp($a['OrderProduct']['pro_code'], $b['OrderProduct']['pro_code']);

}

//  Sort array with usort
function sort_array(&$a) {
    usort($a, 'compare');

}

//  Print array
function print_a(&$a) {
    print '<pre>';
    print_r($a);
    print '</pre>';

}

function list_merge(&$a,  &$b) {
    $resp = array();

    $ia = 0;
    $ib = 0;
    while($ia < count($a) || $ib < count($b)) {
        //  Check if any of the arrays reached its end
        //  If not, check for merge
        if(isset($a[$ia]) && isset($b[$ib])) {
            //  Product codes are matching, 
            //  Push merged to $resp
            if(strcmp($a[$ia]['OrderProduct']['pro_code'], $b[$ib]['OrderProduct']['pro_code']) == 0) {
                $resp[] = array(
                    'OrderProduct'  => array(
                            'pro_code'  => $a[$ia]['OrderProduct']['pro_code'],
                            'totalQTY'  => $a[$ia]['OrderProduct']['totalQTY'] + $b[$ib]['OrderProduct']['totalQTY'],
                    ),
                );

                //  If merge increment both
                $ia++;
                $ib++;

            }
            //  Product code of element of $a is lesser,
            //  Push $a to $resp
            elseif(strcmp($a[$ia]['OrderProduct']['pro_code'], $b[$ib]['OrderProduct']['pro_code']) < 0) {
                $resp[] = array(
                    'OrderProduct'  => array(
                            'pro_code'  => $a[$ia]['OrderProduct']['pro_code'],
                            'totalQTY'  => $a[$ia]['OrderProduct']['totalQTY'],
                    ),
                );

                //  Increment only pushed
                $ia++;

            }
            //  Product code of element of $b is lesser,
            //  Push $b to $resp
            else {
                $resp[] = array(
                    'OrderProduct'  => array(
                            'pro_code'  => $b[$ib]['OrderProduct']['pro_code'],
                            'totalQTY'  => $b[$ib]['OrderProduct']['totalQTY'],
                    ),
                );

                //  Increment only pushed
                $ib++;

            }

        }
        //  Else automatically push the existing array
        //  If $a exists
        elseif(isset($a[$ia])) {
            $resp[] = array(
                'OrderProduct'  => array(
                        'pro_code'  => $a[$ia]['OrderProduct']['pro_code'],
                        'totalQTY'  => $a[$ia]['OrderProduct']['totalQTY'],
                ),
            );

            //  Increment only pushed
            $ia++;

        }
        //  Else automatically push the existing array
        //  If $b exists
        else {
            $resp[] = array(
                'OrderProduct'  => array(
                        'pro_code'  => $b[$ib]['OrderProduct']['pro_code'],
                        'totalQTY'  => $b[$ib]['OrderProduct']['totalQTY'],
                ),
            );

            //  Increment only pushed
            $ib++;

        }

    }

    return $resp;

}


//  Data structures
$array1 = array(
    array(
        'OrderProduct'  => array(
                'pro_code'  => 'B1',
                'totalQTY'  => 4,
        ),
    ),
    array(
        'OrderProduct'  => array(
                'pro_code'  => 'B2',
                'totalQTY'  => 4,
        ),
    ),
    array(
        'OrderProduct'  => array(
                'pro_code'  => 'B4',
                'totalQTY'  => 4,
        ),
    ),
);

$array2 = array(
    array(
        'OrderProduct'  => array(
                'pro_code'  => 'B1',
                'totalQTY'  => 360,
        ),
    ),
    array(
        'OrderProduct'  => array(
                'pro_code'  => 'B2',
                'totalQTY'  => 600,
        ),
    ),
    array(
        'OrderProduct'  => array(
                'pro_code'  => 'B3',
                'totalQTY'  => 600,
        ),
    ),
);


//  Sort arrays by product code
sort_array($array1);
sort_array($array2);

//  Merge arrays with list merge
$array3 = list_merge($array1, $array2);

//  Print arrays for check
print_a($array1);
print_a($array2);
print_a($array3);

我希望,我可以提供任何帮助。

答案 1 :(得分:1)

这和我的方法一样精简。它实际上是3个简单的步骤,具有自定义功能。

代码:

 foreach {a b c} $list1 {
      dict lappend mydict key1 $a
      dict lappend mydict key2 $b
      dict lappend mydict key3 $c
 }

自定义函数说明:$QTY=[ ["OrderProduct"=> ["pro_code"=>"B1","totalQTY"=>"4"]], ["OrderProduct"=> ["pro_code"=>"B2","totalQTY"=>"4"]], ["OrderProduct"=> ["pro_code"=>"B4","totalQTY"=>"4"]] ]; $DSQTY=[ ["OrderProduct" => ["pro_code"=>"B1","totalDistSalesQTY"=>"360"]], ["OrderProduct"=> ["pro_code"=>"B2","totalDistSalesQTY"=>"600"]], ["OrderProduct"=> ["pro_code"=>"B3","totalDistSalesQTY"=>"600"]] ]; function getDeepColumn($a,$c,$result=[]){ foreach(array_column(array_column($a,"OrderProduct"),$c,'pro_code') as $k=>$v){ $result[$k][$c]=$v; } return $result; } $merged=array_merge_recursive(getDeepColumn($QTY,'totalQTY'),getDeepColumn($DSQTY,'totalDistSalesQTY')); ksort($merged); // make sure B4 is not before B3 foreach($merged as $k=>$a){ $result[]=["OrderProduct"=>array_merge(["pro_code"=>$k],$a)]; } var_export($result); 使用带有指定数组的array_column()和指定的列名称从所有getDeepColumn()子数组中提取所需的值。列值临时存储在名为OrderProduct的数组数组中。 $result的第一级密钥是$result值,以便将来合并。 pro_code的子数组由指定列的名称(作为键)和指定列的值(作为值)组成。

首先,使用array_merge_recursive()将所需的深列值混合在一起。

接下来,$resultksort()'ed(使用唯一的$merge键)。

最后,使用foreach(),重新索引所有pro_code个子数组,并将OrderProduct值返回到pro_code子数组中的正确位置。

输出:

OrderProduct

答案 2 :(得分:0)

如果您将产品代码用作结果数组中的键,则非常简单。

// combine the two arrays together and iterate all their rows
foreach (array_merge($array1, $array2) as $row) {

    // get the code
    $code = $row['OrderProduct']['pro_code'];

    // get the previous value for that code, or an empty array if there isnt' one
    $prev = $result[$code]['OrderProduct'] ?? [];

    // merge the previous value with the new value
    $result[$code]['OrderProduct'] = array_merge($prev, $row['OrderProduct']);
}

您最终会在结果数组中使用产品代码键,这可能很好。如果正常,您可以使用$result = array_values($result)删除它们。