【问题标题】:How can I optimize my array_join (simulates a LEFT JOIN) function?如何优化我的 array_join(模拟 LEFT JOIN)函数?
【发布时间】:2012-08-01 17:17:28
【问题描述】:

我编写了以下代码以在 PHP 中获取数组并将它们“连接”在一起,就像在 MySQL 中使用 LEFT JOIN 一样。为了我的缘故,我使用 foreach 编写了函数,并将数组传入并返回了一个新数组……我觉得它的可读性很好,但我也知道它效率低下。

理想情况下,我希望这个函数能够处理每个数组超过 10,000 行,我怀疑这意味着:1)通过引用传递 $original(以节省内存),以及 2)使用 PHP 迭代数组函数之一,而不是比 foreach (以节省处理时间)。

通常我不会发布这类“测验”之类的问题,但我觉得这个问题的答案会让社区受益。 (喜欢这个人:Join 2 multidimensional array

愿 1) 最快和 2) 最低内存消耗的答案获胜! :P

<?php

// Join Arrays on Keys (**updated with knittl's suggestion**)
function array_join($original, $merge, $on) {
    if (!is_array($on)) $on = array($on);
    foreach ($merge as $remove => $right) {
        foreach ($original as $index => $left) {
            foreach ($on as $from_key => $to_key) {
                if (!isset($original[$index][$from_key])
                    || !isset($right[$to_key])
                    || $original[$index][$from_key] != $right[$to_key])
                    continue 2;
            }
            $original[$index] = array_merge($left, $right);
            unset($merge[$remove]);
        }
    }
    return array_merge($original, $merge);
}

// Test Arrays
$data1 = array(
    array(
        'productId' => '822335',
        'dateHour' => '2011-11-17 06:00:00',
        'qtySold' => '200',
        'qtyCanceled' => '10',
    ),
    array(
        'productId' => '822335',
        'dateHour' => '2011-11-17 07:00:00',
        'qtySold' => '100',
        'qtyCanceled' => '20',
    ),
    array(
        'productId' => '822336',
        'dateHour' => '2011-11-17 06:00:00',
        'qtySold' => '0',
        'qtyCanceled' => '30',
    ),
    array(
        'productId' => '822336',
        'dateHour' => '2011-11-17 07:00:00',
        'qtySold' => '50',
        'qtyCanceled' => '40',
    ),
);

$data2 = array(
    array(
        'entity_id' => '822335',
        'dateHour' => '2011-11-17 06:00:00',
        'productInventory' => '300',
    ),
    array(
        'entity_id' => '822335',
        'dateHour' => '2011-11-17 07:00:00',
        'productInventory' => '200',
    ),
    array(
        'entity_id' => '822336',
        'dateHour' => '2011-11-17 06:00:00',
        'productInventory' => '100',
    ),
    array(
        'entity_id' => '822336',
        'dateHour' => '2011-11-17 07:00:00',
        'productInventory' => '50',
    ),
);

// Usage
$result = array_join($data1, $data2, array(
    'productId' => 'entity_id',
    'dateHour' => 'dateHour'
));
print_r($result);

【问题讨论】:

  • break 添加到你最里面的foreach+if ...这应该会大大加快执行速度。
  • 以下是三种“基本”连接技术:LOOPHASHMERGE。以上是哪一个?其他人将如何工作?每个的 Big-O 是什么?
  • @knittl:不幸的是,打破任何 foreach 都会阻止多键匹配工作。
  • @CalebGray: foreach ($on as $from_key =&gt; $to_key) { if (!isset...) $match = false; } 你永远不会将 $match 改回 TRUE。所以将其更改为{ $match = FALSE; break; } 肯定会有所帮助。很多。使用 continue; 语句跳过外循环的一次迭代甚至有助于节省该状态变量 ($match)。
  • @knittl:哦,你完全正确!哈!我在重读我的实现之前发言。我会更新我的问题。 ^_^

标签: php


【解决方案1】:

更好?

function array_join($original, $merge, $on) {
    if (!is_array($on)) $on = array($on);
    foreach ($merge as $remove => $right) {
        foreach ($original as $index => $left) {
            foreach ($on as $from_key => $to_key) {
                if (!isset($original[$index][$from_key])
                || !isset($right[$to_key])
                || $original[$index][$from_key] != $right[$to_key])
                    continue 2;
            }
            $original[$index] = array_merge($left, $right);
            unset($merge[$remove]);
        }
    }
    return array_merge($original, $merge);
}

【讨论】:

  • 太棒了!看起来你的优化是我想要的。 ^_^
  • @knittl 你为什么要返回 array_merge($original, $merge) 而不仅仅是返回 $original
  • @CalebGray ^^ 如果你知道答案,同样的问题
  • @Nathan:快 4 年了,我真的不能再说了。它将添加仍然留在$merge 数组中的所有键。
猜你喜欢
  • 2012-04-02
  • 1970-01-01
  • 1970-01-01
  • 2012-11-27
  • 2021-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多