Php 如何有效地将两个(或多个)具有公共键的关联数组组合在一起

Php 如何有效地将两个(或多个)具有公共键的关联数组组合在一起,php,python,arrays,merge,Php,Python,Arrays,Merge,更一般地说,我们有两个不同长度的列表,具有一个公共属性: list1: { {"orderID":1234, "FirstName":"shaheeb", "LastName":"roshan"}, {"orderID":9183, "FirstName":"robert", "LastName":"gibbons"}, {"orderID":2321, "FirstName":"chester"}, } list2: {

更一般地说,我们有两个不同长度的列表,具有一个公共属性:

list1: {
         {"orderID":1234, "FirstName":"shaheeb", "LastName":"roshan"},
         {"orderID":9183, "FirstName":"robert", "LastName":"gibbons"},
         {"orderID":2321, "FirstName":"chester"},
       }
list2: {
         {"orderID":1234, "cell":"555-555-5555", "email":"roshan@fake.com"},
         {"orderID":2321, "email":"chester@fake.com"},
       }
我希望将这些合并为:

list3: {
         {"orderID":1234, "FirstName":"shaheeb", "LastName":"roshan", "cell":"555-555-5555", "email":"roshan@fake.com"},
         {"orderID":9183, "FirstName":"robert", "LastName":"gibbons"},
         {"orderID":2321, "FirstName":"chester", "email":"chester@fake.com"},
       }
我主要是一名PHP开发人员,我提出了以下建议:

function mergeArrays($a1, $a2) {
    $larger = (count($a1) > count($a2)) ? $a1 : $a2;
    $smaller = ($larger == $a1) ? $a2 : $a1;
    $combinedArray = array();
    foreach ($larger AS $key=>$largerSet) {
        $combinedRow = array();
        if (isset ($smaller[$key]) ) {
            $combinedRow = $largerSet + $smaller[$key];
            $combinedArray[$key] = $combinedRow;
        }else {
            $combinedArray[$key] = $largerSet;
        }
    }
    return ($combinedArray);
}
$array1 = array("12345"=>array("OrderID"=>12345, "Apt"=>"blue"));
$array2 = array(
                "12345"=>array("OrderID"=>12345, "AnotherCol"=>"Goons", "furtherColumns"=>"More Data"),
                "13433"=>array("OrderID"=>32544, "Yellow"=>"Submarine")
            );
array(2) {
  [12345]=>
  array(4) {
    ["OrderID"]=>
    int(12345)
    ["AnotherCol"]=>
    string(5) "Goons"
    ["furtherColumns"]=>
    string(9) "More Data"
    ["Apt"]=>
    string(4) "blue"
  }
  [13433]=>
  array(2) {
    ["OrderID"]=>
    int(32544)
    ["Yellow"]=>
    string(9) "Submarine"
  }
}
如果使用以下各项进行测试:

function mergeArrays($a1, $a2) {
    $larger = (count($a1) > count($a2)) ? $a1 : $a2;
    $smaller = ($larger == $a1) ? $a2 : $a1;
    $combinedArray = array();
    foreach ($larger AS $key=>$largerSet) {
        $combinedRow = array();
        if (isset ($smaller[$key]) ) {
            $combinedRow = $largerSet + $smaller[$key];
            $combinedArray[$key] = $combinedRow;
        }else {
            $combinedArray[$key] = $largerSet;
        }
    }
    return ($combinedArray);
}
$array1 = array("12345"=>array("OrderID"=>12345, "Apt"=>"blue"));
$array2 = array(
                "12345"=>array("OrderID"=>12345, "AnotherCol"=>"Goons", "furtherColumns"=>"More Data"),
                "13433"=>array("OrderID"=>32544, "Yellow"=>"Submarine")
            );
array(2) {
  [12345]=>
  array(4) {
    ["OrderID"]=>
    int(12345)
    ["AnotherCol"]=>
    string(5) "Goons"
    ["furtherColumns"]=>
    string(9) "More Data"
    ["Apt"]=>
    string(4) "blue"
  }
  [13433]=>
  array(2) {
    ["OrderID"]=>
    int(32544)
    ["Yellow"]=>
    string(9) "Submarine"
  }
}
合并阵列$array1,$array2输出以下内容:

function mergeArrays($a1, $a2) {
    $larger = (count($a1) > count($a2)) ? $a1 : $a2;
    $smaller = ($larger == $a1) ? $a2 : $a1;
    $combinedArray = array();
    foreach ($larger AS $key=>$largerSet) {
        $combinedRow = array();
        if (isset ($smaller[$key]) ) {
            $combinedRow = $largerSet + $smaller[$key];
            $combinedArray[$key] = $combinedRow;
        }else {
            $combinedArray[$key] = $largerSet;
        }
    }
    return ($combinedArray);
}
$array1 = array("12345"=>array("OrderID"=>12345, "Apt"=>"blue"));
$array2 = array(
                "12345"=>array("OrderID"=>12345, "AnotherCol"=>"Goons", "furtherColumns"=>"More Data"),
                "13433"=>array("OrderID"=>32544, "Yellow"=>"Submarine")
            );
array(2) {
  [12345]=>
  array(4) {
    ["OrderID"]=>
    int(12345)
    ["AnotherCol"]=>
    string(5) "Goons"
    ["furtherColumns"]=>
    string(9) "More Data"
    ["Apt"]=>
    string(4) "blue"
  }
  [13433]=>
  array(2) {
    ["OrderID"]=>
    int(32544)
    ["Yellow"]=>
    string(9) "Submarine"
  }
}
但我觉得这不是最优雅的解决方案。例如,我应该能够组合n个数组。我真的不知道我将如何做到这一点。另外,只要看一下这些代码,我就相当肯定有更有效的方法来实现这一需求

作为一个学习点,我很好奇python专家是否会借此机会向我们展示PHP。就这一点而言,我很好奇Excel/VBA是否能够处理这个问题。这就是我开始尝试解决这个问题的原因,我认为excel肯定可以处理列表

我完全明白,这个问题有很多不同的说法。我已经看过其中的几个,仍然觉得我应该在这里尝试我的版本

非常感谢你的想法

谢谢大家!


SR

对于Python中的通用解决方案,对于任意数量的列表:

orders = defaultdict(dict)
for order_list in order_lists:
    for order in order_list:
        orders[order['orderID']].update(order)

请参见联机工作:

了解Python的通用解决方案,了解任意数量的列表:

orders = defaultdict(dict)
for order_list in order_lists:
    for order in order_list:
        orders[order['orderID']].update(order)

在线查看它的工作情况:

好吧,您可以随时将函数替换为。

好吧,您可以随时将函数替换为。

一个通用解决方案,可以合并任意数量的dict或dict列表-如果您有多个列表,只需在调用函数之前将它们添加在一起:

from collections import defaultdict

def merge_dicts_by_key(key, *dicts):
    return reduce(lambda acc,val: acc[val[key]].update(val) or acc,
                  dicts,
                  defaultdict(dict))
这样称呼:

merge_dicts_by_key('orderId', dict1, dict2, dict3)
或者,如果您有目录列表:

merge_dicts_by_key('orderId', *list_of_dicts)
merge_dicts_by_key('orderId', *(list1 + list2))

可以合并任意数量的DICT或DICT列表的通用解决方案-如果您有多个列表,只需在调用函数之前将它们添加到一起即可:

from collections import defaultdict

def merge_dicts_by_key(key, *dicts):
    return reduce(lambda acc,val: acc[val[key]].update(val) or acc,
                  dicts,
                  defaultdict(dict))
这样称呼:

merge_dicts_by_key('orderId', dict1, dict2, dict3)
或者,如果您有目录列表:

merge_dicts_by_key('orderId', *list_of_dicts)
merge_dicts_by_key('orderId', *(list1 + list2))

您是在寻找PHP解决方案还是Python解决方案?我认为是Python,对吗?要么1使语言不可知,例如组合理论,这很无聊,要么2只留下一个语言标记:-算法可能太复杂,包含较大/较小的内容。真正发生的是对某个属性或属性集的连接,这是一个由两部分组成的操作检测-查找可连接的值-和合并。您是在寻找PHP解决方案还是Python解决方案?我认为是Python,对吗?要么1使语言不可知,例如组合理论,这很无聊,要么2只留下一个语言标记:-算法可能太复杂,包含较大/较小的内容。真正发生的是对某个属性或属性集的连接,这是一个由两部分组成的操作检测-查找可连接的值-和合并。请注意,我相信这将与Python 2.7或更高版本一起使用-+1获得一个非常好的答案!在我对这个问题的回答中,我已经编写了一个更通用的形式。作为说明,这将适用于Python 2.7或更高版本-+1,这是一个非常好的答案!在我对这个问题的回答中,我已经编写了一个更通用的形式;但我把它们放在正确的位置,这对我来说仍然不起作用。我搞不懂为什么。修正了那里的订单。你是怎么调用它的?发现了问题。忘记了x.updatey在完成时并没有实际返回x,reduce希望函数返回结果,而不是修改累加器。将or acc添加到lambda的末尾修复了它,因为更新不会返回任何结果,因此or将始终计算为新更新的acc。啊,太好了+1然后是一个简洁和一般的解决方案。事实上,我在测试前对它进行了升级:你的lambda和dicts被交换;但我把它们放在正确的位置,这对我来说仍然不起作用。我搞不懂为什么。修正了那里的订单。你是怎么调用它的?发现了问题。忘记了x.updatey在完成时并没有实际返回x,reduce希望函数返回结果,而不是修改累加器。将or acc添加到lambda的末尾修复了它,因为更新不会返回任何结果,因此or将始终计算为新更新的acc。啊,太好了+1然后是一个简洁和一般的解决方案。实际上,我在测试前对它进行了升级: