PHP代码,用于比较两个具有约300000个条目和输出差异的大型文本文件

PHP代码,用于比较两个具有约300000个条目和输出差异的大型文本文件,php,function,Php,Function,我有两个列表A和B,B=A+C-D。所有元素都是唯一的,没有重复项。如何获取以下列表: (1) 新添加的项目,C (2) 已删除的旧项目,D C和D不超过10000个元素左右 编辑 废话,抱歉,伙计们-忘了重要的细节-这些都是文本文件,不是内存元素 function diffLists($listA,$listB) { $resultAdded = array(); $resultRemoved = array(); foreach($listB AS $item) {

我有两个列表A和B,B=A+C-D。所有元素都是唯一的,没有重复项。如何获取以下列表:
(1) 新添加的项目,C
(2) 已删除的旧项目,D

C和D不超过10000个元素左右

编辑 废话,抱歉,伙计们-忘了重要的细节-这些都是文本文件,不是内存元素

function diffLists($listA,$listB) {

  $resultAdded = array();
  $resultRemoved = array();
  foreach($listB AS $item) {
    if (!in_array($item,$listA)) {
       $resultAdded[] = $item;
    }
  }
  foreach($listA AS $item) {
    if (!in_array($item,$listB)) {
      $resultRemoved[] = $item;
    }
  }
  return array($resultAdded,$resultRemoved);
}



$myListA = array('item1','item2','item3');
$myListB = array('item1','item3','item4');
print_r(diffLists($myListA,$myListB));

这将输出一个包含2个元素的数组。第一个元素是在列表B中添加的项目列表,第二个元素是在列表B中删除的项目列表。

如果要更有效地执行此操作,您可能需要尝试Levenshtein算法


在B中搜索A的每个值(反之亦然)具有O(n^2)复杂性


对于大量数据,您可能最好对每个列表进行排序O(n logn),然后对排序后的列表进行一次遍历,计算添加/删除的元素。(相对容易做到,因为你知道没有重复项。)

我认为数组的大小是无关紧要的,除非你真的想关注这个操作的性能,也就是说,你每单位时间要执行特定数量的执行

如果你只是需要做它来完成它,这对我来说似乎很微不足道


最有效的方法是首先对列表进行排序,并尽可能少地访问数组元素。例如:

<?php

sort($a, SORT_NUMERIC);
sort($b, SORT_NUMERIC);
$c = array();
$d = array();
while (($currA = array_pop($a)) !== null) {
        while (($currB = array_pop($b)) !== null) {
                if ($currB == $currA) {
                        // exists in both, skip value
                        continue 2;
                }
                if ($currA > $currB) {
                        // exists in A only, add to D, push B back on to stack
                        $d[] = $currA;
                        $b[] = $currB;
                        continue 2;
                }
                // exists in B only, add to C
                $c[] = $currB;
        }
        // exists in A only, for values of A < all of B
        $d[] = $currA;
}

您说过您已经有两个文件A和B

假设您在Unix系统上运行,下面是最简单、最快的解决方案

system("comm -13 A B > C");
system("comm -23 A B > D");

//read C and D in PHP

我们在谈论桌子和MySQL吗?你们有两张桌子(a、b)还是四张桌子(a、b、c、d)。新项目与什么相比?约会?你有没有一个表格来记录哪些元素被删除了?你需要另一张桌子吗?你的问题很含糊。我不知道这比仅仅使用
array\u diff()
有什么好处?最终,您将在_array()中调用大约600000个
here@Tom-我下意识的反应是同意您的意见,因为此解决方案中的每个foreach块都复制了数组_diff。但我对10k和20k元素数组进行了一些基准测试,令人震惊的是,foreach循环的运行速度比数组_diff快得多,可以获得较大的输入。不过,它仍然比我发布的排序和搜索解决方案慢几个数量级。啊,array_diff目前在性能方面存在缺陷:我认为你太快就忽略了性能的相关性。如果生成的数组如OP所说的每个都是~10k行,那么输入数组如果不是更大的话,至少也会有那么大。试着用$a=range(110000)和$b=range(220000,2)创建10k元素输入数组,然后运行您的方法,对我来说,这需要14秒(web请求的时间永远很长)。将其增加到20k个元素输入数组,其中$a=范围(120000)和$b=范围(240000,2),需要45秒。使用我为这个问题发布的解决方案,第一个案例需要0.02秒,第二个案例需要0.04秒。@Kevin-我理解所有这些-甚至在我发布之前。但谁说这是一个网络请求?你的解决方案很棒——但这并不意味着你不能一次性使用廉价的暴力。更不用说我在表现上完全符合我的要求。我认为说“我驳回了它”是相当不准确的。@Peter-很公平,但问题的标题是30万行列表。我厌倦了等待array_diff完成这种大小的输入(它仍在运行,11分钟以上,我的cpu被锁定),而我发布的解决方案仍然花费了<2秒的时间。我认为array_diff解决方案太快地忽略了数组大小的相关性。即使这不是一个web请求,谁还想测试每个测试用例运行这么长时间的代码?array_diff的速度问题似乎是在5.2.4(2009年初)之后引入的一个bug,因此,如果该bug得到解决,我的评论可能完全不相关。链接票证确实有一个解决方案,在这种情况下可以很好地工作,并且比我提供的解决方案更快。速度+1。我只想补充一点,这是对原始阵列的破坏——因此,如果这对OP有影响,他应该先复制它们。非常漂亮!对我来说非常有用!!谢谢你,威尔!
system("comm -13 A B > C");
system("comm -23 A B > D");

//read C and D in PHP