【问题标题】:How to join similar elements of array with PHP如何用 PHP 连接数组的相似元素
【发布时间】:2019-11-12 10:18:30
【问题描述】:

我们正在一个巨大的列表(包含 500 万个元素的数组)上运行 PHP 代码。

列表格式如下(乍一看很“奇怪”,但这是迄今为止我们为了优化下面代码的速度而推出的最好的格式)

$array = array(

    array(1 => true,3 => true),
    array(2 => true,4 => true,6 => true),
    array(3 => true,5 => true),
    array(5 => true),
    array(4 => true,8 => true,10 => true),
    array(200 => true,300 => true)

);

我们想将上面数组中相似的元素组合起来得到这样的结果:

$final_array = array(

    array(1,3,5),
    array(2,4,6,8,10),
    array(200,300)

);

我们决定使用array(1 => true,3 => true),而不是使用array(1,3),因为使用键而不是值(用于存储信息)使下面的代码运行得更快,并且它输出$final_array 和上面一样。

foreach ($array as $key1 => $value1) {

    foreach ($array as $key2 => $value2) {

        if ($key1 != $key2) {

            foreach ($array[$key1] as $key3 => $value3) {

                if (isset($array[$key2][$key3])) {

                    $array[$key2] = $array[$key2] + $array[$key1];

                    unset($array[$key1]);

                    break 2;

                }

            }   

        }

    }

}

但是上面的代码仍然很慢。您能找到一种更好的方法,以更快的代码将相似的元素相互聚合吗?

【问题讨论】:

  • 你想达到什么目的?
  • @YasinPatel 我们希望将数组中相似的元素连接在一起,这些元素是分开的。例如:如果有一个元素包含 1,2,另一个元素包含 2,4,我们希望将它们全部连接起来,然后将 1,2,4 放在一个最终数组中。
  • 真的不清楚为什么 1,3,5 相似但 2,4,6,8,10 不相似。但它们彼此相似。相似是指奇数和偶数吗?
  • 或者你的意思是你想摆脱重复?
  • @RiggsFolly 让我澄清一下:如果一个元素有 1,2 而另一个元素有 2,4,那么这两个元素之间有一个“链接”,即数字 2。如果 1 和 2 在一起如果 2 和 4 在一起,那么 1 和 4 必须和 2 在一起。我找不到更好的英语表达方式抱歉。

标签: php arrays performance recursion


【解决方案1】:

array_intersect_key代替第三个循环怎么样?

$array = array(
    array(1 => true,3 => true),
    array(2 => true,4 => true,6 => true),
    array(3 => true,5 => true),
    array(5 => true),
    array(4 => true,8 => true,10 => true),
    array(200 => true,300 => true)

);
foreach ($array as $key => $value) {
    foreach ($array as $key2 => $value2) {
        if ($key !== $key2 && !empty(array_intersect_key($value, $value2))) {
            $array[$key] = $value2 + $value;
            unset($array[$key2]);
        }
    }
}

print_r($array);

Working example

编辑#1: 为了获得更好的性能,请尝试以下变体:

$array = array(
    array(1 => true,3 => true),
    array(2 => true,4 => true,6 => true),
    array(3 => true,5 => true),
    array(5 => true),
    array(4 => true,8 => true,10 => true),
    array(200 => true,300 => true)

);
$count = count($array);
for ($i = 0; $i < $count - 1; ++$i) {
    for ($j = $i + 1; $j < $count; ++$j) {
        if (!empty(array_intersect_key($array[$i], $array[$j]))) {
            $array[$j] = $array[$i] + $array[$j];
            unset($array[$i]);
            continue 2;
        }
    }
}

Working example #2

【讨论】:

  • 你的代码比我们的漂亮多了,读起来也更清晰! \o/ 但是它运行速度较慢。原因是array_intersect_key 不会停止,直到检查参数数组的所有元素。另一方面,当找到一个匹配项时,我在顶部 breaks 发布的代码。我很伤心,我真的以为你的代码会更快!
  • @Samul 检查请更新答案,我想它有更好的性能
  • 使用for 代替forach 改进但不是很多(我测试了1m 次迭代)。我尝试用if (!array_intersect_key($array[$i], $array[$j])) { 替换if (!empty(array_intersect_key($array[$i], $array[$j]))) { 并且工作得稍微好一点,但仍然不比我的原始代码好。令我惊讶的是array_intersect_key 并没有慢多少,如果有办法让它在找到相交时“停止”处理,肯定会比原始代码更好。
【解决方案2】:
$arr = array('Hello','World!','Beautiful','Day!');
echo join(" ",$arr);

See Details

【讨论】:

  • kkkk值得一试!但是,到目前为止,这一天进展并不顺利,我们在这个项目中延迟了 2 个月,并且我们被困在后端的性能优化中
  • 然后尝试使用 array_merge() 函数。
猜你喜欢
  • 2013-05-22
  • 2015-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-08
  • 1970-01-01
相关资源
最近更新 更多