PHP-比较两个数组时提高速度

时间:2018-09-19 16:07:56

标签: php arrays

我有两个单独的数组,如下所示:

$array = array(
  array("id" => "1", "name" => "name1"),
  array("id" => "2", "name" => "name2"),
  array("id" => "3", "name" => "name3"),
  array("id" => "4", "name" => "name4"),
  array("id" => "5", "name" => "name5"),
  array("id" => "6", "name" => "name6"),
  array("id" => "7", "name" => "name7"),
  array("id" => "8", "name" => "name8"),
  array("id" => "9", "name" => "name9"),
  array("id" => "10", "name" => "name10"),
  array("id" => "11", "name" => "name11"),
  array("id" => "12", "name" => "name12"),
);

$array1 = array(
  array("id" => "1", "description" => "description1"),
  array("id" => "2", "description" => "description2"),
  array("id" => "3", "description" => "description3"),
  array("id" => "4", "description" => "description4"),
  array("id" => "5", "description" => "description5"),
  array("id" => "6", "description" => "description6"),
  array("id" => "7", "description" => "description7"),
  array("id" => "8", "description" => "description8"),
  array("id" => "9", "description" => "description9"),
  array("id" => "10", "description" => "description10"),
  array("id" => "11", "description" => "description11"),
  array("id" => "12", "description" => "description12"),
);

我想根据ID号比较和匹配两个数组的名称和描述。我想出了以下代码:

foreach($array as $value){
      foreach($array1 as $value1){
        if($value['id'] == $value1['id']){
          echo "name is ".$value['name']. " and description is ".$value1['description']."<p>";

          }
        }
  }

显示结果:

name is name1 and description is description1

name is name2 and description is description2

name is name3 and description is description3

name is name4 and description is description4

name is name5 and description is description5

name is name6 and description is description6

name is name7 and description is description7

name is name8 and description is description8

name is name9 and description is description9

name is name10 and description is description10

name is name11 and description is description11

name is name12 and description is description12

这正是我想要的,但是我想知道是否有一种方法可以减少代码的运行时间,因为我两次使用了foreach,因此需要遍历每个数组来检查ID号是否匹配。我将拥有一个包含100多个数组的数组,并且需要比较两个数组以找到匹配的值。因此,它可能很慢。除了foreach之外,还有没有其他方法可以比较两个数组?

5 个答案:

答案 0 :(得分:1)

将两个数组组合为一个的最简单方法是两次调用array_column以通过ID字段对其重新编制索引,然后调用array_replace_recursive将两个数组组合在一起:

$array = array_column($array, null, 'id');
$array1 = array_column($array1, null, 'id');

$merged = array_replace_recursive($array, $array1);

然后,您可以循环遍历行,并且一次只处理单个项目的显示:

foreach ($merged as $row) {
  echo "name is {$row['name']} and description is {$row['description']}", PHP_EOL;
}
  

名称是name1,描述是description1
  ...

请参见https://eval.in/1058846

答案 1 :(得分:0)

不是真的,除非

  1. 您知道两个数组包含相同顺序的相同ID。然后,您可以使用一个数组中的键引用另一个数组。

    foreach ($array as $key => $value) {
        echo "name is $value[name] and description is $value1[$key][description]<p>";
    }
    
  2. 您可以使用id作为键以某种方式索引两个数组。根据您获得它们的方式,您也许可以以此方式构建它们。例如,当从数据库结果中将行提取到数组中时,将该字段用作键。

    while($row = $result->fetch()) {
        $array[$row['id']] = $row;
    }
    // then you can use the same foreach as above even if the results
    // aren't in the same order.
    

    (如果数组确实确实来自数据库,则应考虑使用联接并通过一个查询获取它们。)

除此之外,可以加快您当前正在使用的嵌套foreach的一件事是,如果您找到匹配项后将break移出内循环。

答案 2 :(得分:0)

代替两个数组的倍数,只需要每个数组一次并合并它们。这完全取决于您获得什么数据以及想要拥有什么数据。

$array = array(
    array("id" => "1", "name" => "name1"),
    array("id" => "2", "name" => "name2"),
    array("id" => "3", "name" => "name3"),
    array("id" => "4", "name" => "name4"),
    array("id" => "5", "name" => "name5"),
    array("id" => "6", "name" => "name6"),
    array("id" => "7", "name" => "name7"),
    array("id" => "8", "name" => "name8"),
    array("id" => "9", "name" => "name9"),
    array("id" => "10", "name" => "name10"),
    array("id" => "11", "name" => "name11"),
    array("id" => "12", "name" => "name12"),
);

$array1 = array(
    array("id" => "1", "description" => "description1"),
    array("id" => "2", "description" => "description2"),
    array("id" => "3", "description" => "description3"),
    array("id" => "4", "description" => "description4"),
    array("id" => "5", "description" => "description5"),
    array("id" => "6", "description" => "description6"),
    array("id" => "7", "description" => "description7"),
    array("id" => "8", "description" => "description8"),
    array("id" => "9", "description" => "description9"),
    array("id" => "10", "description" => "description10"),
    array("id" => "11", "description" => "description11"),
    array("id" => "12", "description" => "description12"),
);

$mergedArray = [];
foreach ($array as $row) {
    $mergedArray[$row["id"]] = $row;
}
foreach ($array1 as $row) {
    $mergedArray[$row["id"]]["description"] = $row["description"];
}
var_dump($mergedArray);

输出

array(12) {
  [1]=>
  array(3) {
    ["id"]=>
    string(1) "1"
    ["name"]=>
    string(5) "name1"
    ["description"]=>
    string(12) "description1"
  }
  [2]=>
  array(3) {
    ["id"]=>
    string(1) "2"
    ["name"]=>
    string(5) "name2"
    ["description"]=>
    string(12) "description2"
  }
  [3]=>
  array(3) {
    ["id"]=>
    string(1) "3"
    ["name"]=>
    string(5) "name3"
    ["description"]=>
    string(12) "description3"
  }
  [4]=>
  array(3) {
    ["id"]=>
    string(1) "4"
    ["name"]=>
    string(5) "name4"
    ["description"]=>
    string(12) "description4"
  }
  [5]=>
  array(3) {
    ["id"]=>
    string(1) "5"
    ["name"]=>
    string(5) "name5"
    ["description"]=>
    string(12) "description5"
  }
  [6]=>
  array(3) {
    ["id"]=>
    string(1) "6"
    ["name"]=>
    string(5) "name6"
    ["description"]=>
    string(12) "description6"
  }
  [7]=>
  array(3) {
    ["id"]=>
    string(1) "7"
    ["name"]=>
    string(5) "name7"
    ["description"]=>
    string(12) "description7"
  }
  [8]=>
  array(3) {
    ["id"]=>
    string(1) "8"
    ["name"]=>
    string(5) "name8"
    ["description"]=>
    string(12) "description8"
  }
  [9]=>
  array(3) {
    ["id"]=>
    string(1) "9"
    ["name"]=>
    string(5) "name9"
    ["description"]=>
    string(12) "description9"
  }
  [10]=>
  array(3) {
    ["id"]=>
    string(2) "10"
    ["name"]=>
    string(6) "name10"
    ["description"]=>
    string(13) "description10"
  }
  [11]=>
  array(3) {
    ["id"]=>
    string(2) "11"
    ["name"]=>
    string(6) "name11"
    ["description"]=>
    string(13) "description11"
  }
  [12]=>
  array(3) {
    ["id"]=>
    string(2) "12"
    ["name"]=>
    string(6) "name12"
    ["description"]=>
    string(13) "description12"
  }
}

答案 3 :(得分:0)

您可以通过执行以下操作减少对第二个数组的查找

$array = array(
  array("id" => "1", "name" => "name1"),
  array("id" => "2", "name" => "name2"),
  array("id" => "3", "name" => "name3"),
  array("id" => "4", "name" => "name4"),
  array("id" => "5", "name" => "name5"),
  array("id" => "6", "name" => "name6"),
  array("id" => "7", "name" => "name7"),
  array("id" => "8", "name" => "name8"),
  array("id" => "9", "name" => "name9"),
  array("id" => "10", "name" => "name10"),
  array("id" => "11", "name" => "name11"),
  array("id" => "12", "name" => "name12"),
);

$array1 = array(
  array("id" => "1", "description" => "description1"),
  array("id" => "2", "description" => "description2"),
  array("id" => "3", "description" => "description3"),
  array("id" => "4", "description" => "description4"),
  array("id" => "5", "description" => "description5"),
  array("id" => "6", "description" => "description6"),
  array("id" => "7", "description" => "description7"),
  array("id" => "8", "description" => "description8"),
  array("id" => "9", "description" => "description9"),
  array("id" => "10", "description" => "description10"),
  array("id" => "11", "description" => "description11"),
  array("id" => "12", "description" => "description12"),
);

$ids = array_column($array1, 'id');

foreach($array as $value){
    $index = array_search($value['id'], $ids);
    if(false !== $index){
        $value1 = $array1[$index];
        echo "name is ".$value['name']. " and description is ".$value1['description']."<p>";
    }
}

在这里,我们使用array_column从第二个数组中获取仅包含ID的数组。因为$ids数组是从另一个数组$array1派生的,所以所有数字键在两者之间是相关的。

然后,我们可以轻松地从第一个数组中的当前项目的ID中搜索$ids,以找到该索引,并使用它仅从第二个数组中提取所需的行。

这消除了修改数组结构的需要,并大大简化了工作。但是,如果在单个阵列中有重复的ID,则会出现问题。如果它们来自正确索引的数据库,那么这可能不是问题。

最主要的是,它不需要第二遍foreach迭代遍历大部分无用的项目。您还可以通过添加elsename is name1 and description is description1 name is name2 and description is description2 name is name3 and description is description3 name is name4 and description is description4 name is name5 and description is description5 name is name6 and description is description6 name is name7 and description is description7 name is name8 and description is description8 name is name9 and description is description9 name is name10 and description is description10 name is name11 and description is description11 name is name12 and description is description12 来错误检查第二个数组(如果缺少ID)。

Sandbox

输出

echo "name is ".$value['name']. " and description is ".$value1['description']."<p>";

我应该说这几乎是无效的,因为它是无效的HTML(上面有12个打开的P标签,没有关闭)

foreach($array as $value){
    $intersect = array_intersect($ids, [$value['id']]);
    foreach($intersect as $index=>$id){
       $value1 = $array1[$index];
       if(false !== $index){
          $value1 = $array1[$index];
          echo "name is ".$value['name']. " and description is ".$value1['description']."<p>";
       }
    }
}

如果您有重复的ID

最后,如果您可以有重复的ID,则可以在列上使用array_intersect,然后像这样遍历交叉点:

{{1}}

Sandbox

与原始代码相比,迭代次数要少得多。

答案 4 :(得分:0)

如果仅期望一个结果,则可以使用continue,这样,当找到匹配项时,就不会在其他条目上循环。

给出两个具有10,000个条目的数组,您的方法将花费大约5秒钟,而此代码则花费大约1.4s。

如果您使用的是unixoid操作系统,则可以通过以下方式测量执行时间:

 time php myScript.php

或者您可以使用microtime

<?php
$range = range(1, 1e4, 1);

$array = [];
$array1 = [];

foreach ($range as $i) {
    $array[] = [
        "id" => $i,
        "name" => "name ${i}"
    ];

    $array1[] = [
        "id" => $i,
        "description" => "description ${i}"
    ];
}

$result = [];
foreach ($array as $value) {
    foreach ($array1 as $value1) {
        if ($value["id"] == $value1["id"]) {
            $result[] = "name is " . $value['name'] . " and description is " . $value1['description'] . "<p>";
            continue 2;
        }
    }
}

echo implode("\n", $result);

如果原始速度是主要目标,则可以echo在嵌套的foreach循环中。我更喜欢将数据处理与可视化分开,即使这意味着再次遍历数据也是如此。 (经典的for循环相当便宜,只有真正大的数组大小才会引起关注。)