php - 在循环遍历同一个数组时从当前数组中删除重复项?

时间:2014-03-28 19:50:34

标签: php arrays curl

我正在使用cURL来抓取网页并提取链接。这是针对我的问题的一些代码。

for($i = 0; $i < sizeof($links); $i++){
  $response = crawl($links[$i]);
  //inside this loop i extract links for each crawled html
  $newLinks = getLinks($response);

  //I need to append these new links to current array in loop
  $links= array_values(array_unique(array_merge($links, $newLinks));
}

我需要防止重复链接,所以我不会抓取两次。我想知道这是否是一种安全的方法,或者它是否正确,因为array_values可以重新索引数组的元素,而在循环中,爬行可以为某些链接运行两次。

我可以使用in_array()对$ links和$ newLinks进行测试以避免重复,但我想知道在这里做样本时会发生什么。

2 个答案:

答案 0 :(得分:0)

如果您只通过函数getLinks();

获得一个链接,则此示例有效
$newLink = getLinks($response);
if(!in_array($newLink,$links)){
  $links=array_merge($links, array($newLink));
}

如果您获得更多链接,可以使用foreach链接

foreach($newLinks as $newLink){
    if(!in_array($newLink,$links)){
      $links=array_merge($links, array($newLink));
    }
}

答案 1 :(得分:0)

TL / DR:使用array_merge($ links,array_diff($ newLinks,$ links));

我的理由:

欢迎来到指数增长的土地。随着收集的链接数组的增长,所需的时间将通过屋顶。给array_merge(array_diff($links, $new_links))一个机会。使用此基准测试代码:

function get($num)
{
  $links = array();
  for($i=0;$i<rand(5,20);$i++)
  {
    $links[] = rand(1,$num);
  }
  return $links;
}

function test($iter, $num_total_links)
{
  $unique_time = 0;
  $unique_links = array();
  $diff_time = 0;
  $diff_links = array();
  for($i=0;$i<$iter;$i++)
  {
    $new_links = get($num_total_links);

    $start = microtime(true);
    $unique_links = 
      array_values(array_unique(array_merge($unique_links, $new_links)));
    $end = microtime(true);
    $unique_time += $end - $start;

$start = microtime(true);
$diff_links = array_values(array_merge(array_diff($new_links, $diff_links)));
$end = microtime(true);
$diff_time += $end - $start;
  }
  echo $unique_time . ' - ' . $diff_time;
}

您可以调整值;如果您希望使用相对较少的链接来浏览大量页面,请选择一个大的(不是太大或永远不会花费)$ iter和$ num_total_links。如果您可能会看到许多相同的链接,请相应地减少$ num_total_links。

它归结为一个合并然后唯一的操作总是要求你合并相同数量的链接,而diff和then merge只需要你合并你想要添加的链接。这几乎总是更有效率,即使数量不是很大;通过5到20个链接浏览500页会产生巨大的时间差异,即使少量页面也会显示出明显的差异。

查看数据,与array_unique相比,foreach不是一个糟糕的方法;在做类似的基准测试时,foreach始终如一地击败了array_unique。但两者都是O(n ^ 2),而foreach只是增长得更慢。 array_diff保留O(n)时间,这是你最好的情况;您的算法永远不会比您访问的页数的多倍快。 PHP的内置数组函数将比用PHP编写的任何解决方案都快。

这是数据,随机因素被取出,因为它们所做的只是导致偏差,而不影响结果。我也增加了可能的宇宙&#34;用于说明目的的大量URL;在较小的数字处,array_unique和foreach都生成看起来几乎是线性的图形,尽管它们继续优于array_diff。如果您将其插入Google Charts,您可以看到我正在谈论的内容。

['Number of Pages', 'array_unique', 'array_diff', 'foreach'],
[1, 6.9856643676758E-5, 6.1988830566406E-5, 0.00012898445129395],
[11, 0.0028481483459473, 0.00087666511535645, 0.0014169216156006],
[21, 0.0091345310211182, 0.0017409324645996, 0.0029785633087158],
[31, 0.019546031951904, 0.0023491382598877, 0.0046005249023438],
[41, 0.036402702331543, 0.0032360553741455, 0.006026029586792],
[51, 0.055278301239014, 0.0039372444152832, 0.0078754425048828],
[61, 0.082642316818237, 0.0048537254333496, 0.010209321975708],
[71, 0.11405396461487, 0.0054631233215332, 0.012364625930786],
[81, 0.15123820304871, 0.0062053203582764, 0.014509916305542],
[91, 0.19236493110657, 0.007127046585083, 0.017033576965332],
[101, 0.24052715301514, 0.0080602169036865, 0.01974892616272],
[111, 0.29827189445496, 0.0085773468017578, 0.023083209991455],
[121, 0.35718178749084, 0.0094895362854004, 0.025837421417236],
[131, 0.42515468597412, 0.010404586791992, 0.029412984848022],
[141, 0.49908661842346, 0.011186361312866, 0.033211469650269],
[151, 0.56992983818054, 0.011844635009766, 0.036608695983887],
[161, 0.65314698219299, 0.012562274932861, 0.039996147155762],
[171, 0.74602556228638, 0.013403177261353, 0.04484486579895],
[181, 0.84450364112854, 0.014075994491577, 0.04839038848877],
[191, 0.94431185722351, 0.01488733291626, 0.052026748657227],
[201, 1.0460951328278, 0.015958786010742, 0.056291818618774],
[211, 1.2530679702759, 0.016806602478027, 0.060890197753906],
[221, 1.2901678085327, 0.017560005187988, 0.065101146697998],
[231, 1.4267380237579, 0.018605709075928, 0.070043087005615],
[241, 1.5581474304199, 0.018914222717285, 0.075717210769653],
[251, 1.8255474567413, 0.020106792449951, 0.08226203918457],
[261, 1.8533885478973, 0.020873308181763, 0.085562705993652],
[271, 1.999392747879, 0.021762609481812, 0.15557670593262],
[281, 2.1670596599579, 0.022242784500122, 0.098419427871704],
[291, 2.4296963214874, 0.023237705230713, 0.10490798950195],
[301, 3.0475504398346, 0.031109094619751, 0.13519287109375],
[311, 3.0027780532837, 0.02937388420105, 0.13496232032776],
[321, 2.9123396873474, 0.025942325592041, 0.12607669830322],
[331, 3.0720682144165, 0.026587963104248, 0.13313007354736],
[341, 3.3559355735779, 0.028125047683716, 0.14407730102539],
[351, 3.5787575244904, 0.031508207321167, 0.15093517303467],
[361, 3.6996841430664, 0.028955698013306, 0.15273785591125],
[371, 3.9983749389648, 0.02990198135376, 0.16448092460632],
[381, 4.1213915348053, 0.030521154403687, 0.16835069656372],
[391, 4.3574469089508, 0.031461238861084, 0.17818260192871],
[401, 4.7959914207458, 0.032914161682129, 0.19097280502319],
[411, 4.9738960266113, 0.033754825592041, 0.19744348526001],
[421, 5.3298072814941, 0.035082101821899, 0.2117555141449],
[431, 5.5753719806671, 0.035769462585449, 0.21576929092407],
[441, 5.7648482322693, 0.035907506942749, 0.2213134765625],
[451, 5.9595069885254, 0.036591529846191, 0.2318480014801],
[461, 6.4193341732025, 0.037969827651978, 0.24672293663025],
[471, 6.7780020236969, 0.039541244506836, 0.25563311576843],
[481, 7.0454154014587, 0.039729595184326, 0.26160192489624],
[491, 7.450076341629, 0.040610551834106, 0.27283143997192]