【问题标题】:Merging multidimensional arrays by matching key-value pairs of subarrays?通过匹配子数组的键值对来合并多维数组?
【发布时间】:2017-06-30 15:42:33
【问题描述】:

任务是合并(“廉价”)两个数组,它们具有匹配的子数组键值对。例如:

数组 1:

Array
(
[0] => Array
    (
        [count] => 1
        [da_table] => article
        [da_class] => classes\elements\tables\Article
        [da_page_class] => Page_Article
    )

[1] => Array
    (
        [count] => 2
        [da_table] => client_contract_specification_price
        [da_class] => classes\elements\tables\ClientContractSpecificationPrice
        [da_page_class] => Page_ClientContractSpecification
    )

[2] => Array
    (
        [count] => 2
        [da_table] => supplier
        [da_class] => classes\elements\tables\Supplier
        [da_page_class] => Page_Supplier
    )

)

数组 2:

Array
(
[0] => Array
    (
        [name] => Articles
        [name_short] => 
        [da_page_class] => Page_Article
    )

[1] => Array
    (
        [name] => Client contract specifications
        [name_short] => cc_specifications
        [da_page_class] => Page_ClientContractSpecification
    )

[2] => Array
    (
        [name] => Suppliers
        [name_short] => 
        [da_page_class] => Page_Supplier
    )

)

如何通过匹配的 [da_page_class] => ... 对合并上述两个数组,因此生成的数组将包含第一个和第二个数组的键值,即:

...
[0] => Array
    (
        [count] => 1
        [da_table] => article
        [da_class] => classes\elements\tables\Article
        [da_page_class] => Page_Article
        [name] => Articles
        [name_short] => 
    )
...

附加要求: 子数组可能以随机顺序出现。此外,可能存在“孤儿”,其中包含 ['da_page_class'] 的值,但在另一个数组中没有匹配项。这些应该被忽略。

【问题讨论】:

    标签: php arrays multidimensional-array


    【解决方案1】:

    好吧,您只需遍历数组元素并将它们组合起来:

    <?php
    $data1 = [
        [
            'count' => 1,
            'da_table' => 'article',
            'da_class' => 'classes\elements\tables\Article',
            'da_page_class' => 'Page_Article'
        ],
        [
            'count' => 2,
            'da_table' => 'client_contract_specification_price',
            'da_class' => 'classes\elements\tables\ClientContractSpecificationPrice',
            'da_page_class' => 'Page_ClientContractSpecification'
        ],
        [
            'count' => 2,
            'da_table' => 'supplier',
            'da_class' => 'classes\elements\tables\Supplier',
            'da_page_class' => 'Page_Supplier'
        ]
    ];
    
    $data2 = [
        [
            'name' => 'Articles',
            'name_short' => null,
            'da_page_class' => 'Page_Article'
        ],
        [
            'name' => 'Client contract specifications',
            'name_short' => 'cc_specifications',
            'da_page_class' => 'Page_ClientContractSpecification'
        ],
        [
            'name' => 'Suppliers',
            'name_short' => null,
            'da_page_class' => 'Page_Supplier'
        ]
    ];
    
    $output = [];
    for ($i=0; $i<count($data1); $i++) {
        $output[$i] = array_merge($data1[$i], $data2[$i]);
    }
    print_r($output);
    

    输出明显是:

    Array
    (
        [0] => Array
            (
                [count] => 1
                [da_table] => article
                [da_class] => classes\elements\tables\Article
                [da_page_class] => Page_Article
                [name] => Articles
                [name_short] =>
            )
    
        [1] => Array
            (
                [count] => 2
                [da_table] => client_contract_specification_price
                [da_class] => classes\elements\tables\ClientContractSpecificationPrice
                [da_page_class] => Page_ClientContractSpecification
                [name] => Client contract specifications
                [name_short] => cc_specifications
            )
    
        [2] => Array
            (
                [count] => 2
                [da_table] => supplier
                [da_class] => classes\elements\tables\Supplier
                [da_page_class] => Page_Supplier
                [name] => Suppliers
                [name_short] =>
            )
    
    )
    

    或者,您也可以将第二个数组元素的内容合并到第一个数组的相应元素中。这减少了大型数据集的内存占用。


    考虑到您在评论中指定的附加要求,我更改了合并策略以允许两组的任意顺序:

    <?php
    $data1 = [
        [
            'count' => 1,
            'da_table' => 'article',
            'da_class' => 'classes\elements\tables\Article',
            'da_page_class' => 'Page_Article'
        ],
        [
            'count' => 2,
            'da_table' => 'client_contract_specification_price',
            'da_class' => 'classes\elements\tables\ClientContractSpecificationPrice',
            'da_page_class' => 'Page_ClientContractSpecification'
        ],
        [
            'count' => 2,
            'da_table' => 'supplier',
            'da_class' => 'classes\elements\tables\Supplier',
            'da_page_class' => 'Page_Supplier'
        ]
    ];
    
    $data2 = [
        [
            'name' => 'Articles',
            'name_short' => null,
            'da_page_class' => 'Page_Article'
        ],
        [
            'name' => 'Client contract specifications',
            'name_short' => 'cc_specifications',
            'da_page_class' => 'Page_ClientContractSpecification'
        ],
        [
            'name' => 'Suppliers',
            'name_short' => null,
            'da_page_class' => 'Page_Supplier'
        ]
    ];
    
    $output = [];
    array_walk($data1, function($entry, $key) use (&$output, $data2) {
        $output[$key] = $entry;
        foreach($data2 as $cand) {
            if ($entry['da_page_class'] == $cand['da_page_class']) {
                $output[$key] = array_merge($output[$key], $cand);
            }
        }
    });
    print_r($output);
    

    结果输出显然与上面相同。

    【讨论】:

    • 子数组的顺序可能是随机的,所以简单的合并是行不通的。此外,可能存在“孤儿”,其中包含 ['da_page_class'],但在另一个数组中没有匹配项。
    • @bbe 啊,所以您还有其他未在问题中指定的要求。还有什么要补充的吗?
    • @bbe 好的,我添加了一个版本,实现了修改后的合并策略,允许集合元素的任意顺序。
    • @arkascha 我不确定在当前 PHP 版本中是否仍然如此,但 foreach 过去比 array_walk 和 array_map 快得多
    • masterfloda - 不正确; foreach 和 array_walk 证明了几乎相同的结果; stackoverflow.com/questions/18144782/…
    【解决方案2】:

    O(m*n) 解:

    $result = array();
    
    foreach ($array1 as $value1) {
        // do not handle elements without pageclass
        if (!array_key_exists('da_page_class', $value1) || !$value1['da_page_class']) {
            continue;
        }
    
        foreach ($array2 as $value2) {
            if (!array_key_exists('da_page_class', $value2) || !$value2['da_page_class']) {
                continue;
            }
            if ($value1['da_page_class'] == $value2['da_page_class']) {
                array_push($result, $value1 + $value2)
                break;
            }
        }
    }
    
    print_r($result);
    

    O(m+n) 解:

    $result = array();
    
    foreach ($array1 as $value) {
        // do not handle elements without pageclass
        if (!array_key_exists('da_page_class', $value) || !$value['da_page_class']) {
            continue;
        }
        $result[$value['da_page_class']] = $value;
    }
    foreach ($array2 as $value) {
        if (
            // do not handle elements without pageclass         
            !array_key_exists('da_page_class', $value) || !$value['da_page_class'] ||
            // do not handle elements that do not exist in array 1
            !array_key_exists($value['da_page_class'], $result)
            ) {
            continue;
        }
        // merge values of this pageclass
        $result[$value['da_page_class']] = array_merge($result[$value['da_page_class']], $value);
    }
    
    print_r($result);
    

    编辑:添加 O(m+n) 解决方案

    【讨论】:

    • @bbe 这是使用数组键的 O(m+n) 解决方案
    • 感谢您的努力;抓住“处理”条件。
    • 我首先合并了三个数组,然后使用了 O(m+n) 解决方案:在基于键和工作 (y) 的结果合并数组上,我认为使用 O(2n),因为我有三个数组
    猜你喜欢
    • 2016-06-26
    • 1970-01-01
    • 2019-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-20
    • 2023-03-19
    • 1970-01-01
    相关资源
    最近更新 更多