Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何快速查找排序数组中的元素_Php_Arrays_Csv_Multidimensional Array_Ldap - Fatal编程技术网

Php 如何快速查找排序数组中的元素

Php 如何快速查找排序数组中的元素,php,arrays,csv,multidimensional-array,ldap,Php,Arrays,Csv,Multidimensional Array,Ldap,我是新来这里的,但已经检查了以前关于这方面的帖子,虽然类似,但对于我正在尝试做的事情来说还不够。我有一个包含40K+记录的CSV文件,并检索70K+记录的LDAP记录;两者都存储在多维数组变量中。目标是显示所有不匹配的记录。我目前的解决方案是花20多分钟来处理,效率很低。我创建了一个外部循环,它为每个记录检查LDAP记录集内部循环中的匹配项,如果找到,则跳到下一个记录,并取消LDAP数组索引以缩小下一个循环的数组。我还将两个数组按升序排序,以加快进程。想法、调整、帮助加快流程 foreach($

我是新来这里的,但已经检查了以前关于这方面的帖子,虽然类似,但对于我正在尝试做的事情来说还不够。我有一个包含40K+记录的CSV文件,并检索70K+记录的LDAP记录;两者都存储在多维数组变量中。目标是显示所有不匹配的记录。我目前的解决方案是花20多分钟来处理,效率很低。我创建了一个外部循环,它为每个记录检查LDAP记录集内部循环中的匹配项,如果找到,则跳到下一个记录,并取消LDAP数组索引以缩小下一个循环的数组。我还将两个数组按升序排序,以加快进程。想法、调整、帮助加快流程

foreach($csvArray as $csvindex=>$csvalue) { 
echo "<br />csvArray record: <strong> ".$counter."</strong><br />\n";

  if($counter <= 1) {

      for ($i = 0, $max=$rs["count"]-1; $i < $max ;$i++) { //loop through ldap array
            if($csvalue[0] == $rs[$i]['uid'][0]) { // csv netid & ldap netid
                echo "CSV netid: ".$csvalue[0];
                echo "<br />matched LDAP array [$i] netid: ".$rs[$i]["uid"][0];
                echo "<br />\n";
                $matched = $i; //$i represents integer offset in array (ie. $rs[21])
                break;
            }
      }

    } else {

    unset($rs[$matched]); //remove matched items
    $newRS = array_values($rs); //re-indexes array

    echo "Size of new LDAP array: ".count($newRS);

      for ($i=0, $max=count($newRS); $i<$max; $i++) {
          if($csvalue[0] == $newRS[$i]['uid'][0]) { // csv netid & ldap netid
            echo "<br />CSV netid: ".$csvalue[0];
            echo "<br />matched LDAP array [$i] netid: ".$newRS[$i]["uid"][0];
            echo "<br />\n";
            $matched = $i; //$i represents integer offset in array (ie. $rs[21])
            break;
          }
      }

    } 

$counter++;
}

这里有一些代码来替换您的内部循环。它使用二进制搜索。必须在此点之前对LDAP数组进行排序

$workingArray=$newRS;
while($LDAPcount=count($workingArray)) {
    $indexToCheck=ceil($LDAPcount/2);
    if($csvalue[0] == $workingArray[$indexToCheck]['uid'][0]) { // csv netid & ldap netid
        echo "<br />CSV netid: ".$csvalue[0];
        echo "<br />matched LDAP array ".$workingArray[$indexToCheck]["uid"][0];
        echo "<br />\n";
        $matched = $indexToCheck; //$indexToCheck represents integer offset in array (ie. $rs[21])
        break;
    } else {
        if($csvalue[0] < $workingArray[$indexToCheck]['uid'][0]) {
            $workingArray=array_slice($workingArray,0,$indextoCheck);
        } else {
            $workingArray=array_slice($workingArray,$indextoCheck+1);
        }
    }
 }

代替LDAP记录的直数组,可以考虑树二进制或其他方式。您遇到的效率低下是由于每次都从LDAP列表的开头开始。使用二叉树,您可以按照log2n的顺序设置要检查的LDAP记录的最大数量。如果您在运行过程中从LDAP树中删除节点,这也会对一些人有所帮助。我认为您也不会受到太大的性能影响,因为您目前正在经历对LDAP记录进行排序的过程。只需将该排序替换为加载树。对于70k条记录,LDAP树中最多可检查17条记录。感谢您的回复。我不熟悉LDAP树。如果你能给我指一个参考或例子,那将是一个很大的帮助。我还希望尽可能减少ldap调用的数量。谢谢使用当前已排序的LDAP记录列表,还可以进行二进制搜索。将第一个记录与中间记录进行比较。如果小于中间记录,则下一个LDAP工作列表是LDAP数组的前半部分。然后,再次与中间记录进行比较。重复此操作,直到找到或工作数组长度=0。这种方法实际上比使用树更简单。它正在做你现在正在做的事情,但不是每次都从一开始就开始。太好了,谢谢你!我不是计算机科学专业的学生,所以我首先要考虑算法。看起来会很好用的。稍后我将对此进行一次尝试并发表评论。请注意,此参考说明array_slice效率低下。array_slice本身并不低效,但wikibooks参考是正确的,因为用于此目的的slice效率低下。他们给出了一个更好的算法,使用两个变量来跟踪所需数组部分的顶部和底部。他们的版本很好。
$workingArray=$newRS;
while($LDAPcount=count($workingArray)) {
    $indexToCheck=ceil($LDAPcount/2);
    if($csvalue[0] == $workingArray[$indexToCheck]['uid'][0]) { // csv netid & ldap netid
        echo "<br />CSV netid: ".$csvalue[0];
        echo "<br />matched LDAP array ".$workingArray[$indexToCheck]["uid"][0];
        echo "<br />\n";
        $matched = $indexToCheck; //$indexToCheck represents integer offset in array (ie. $rs[21])
        break;
    } else {
        if($csvalue[0] < $workingArray[$indexToCheck]['uid'][0]) {
            $workingArray=array_slice($workingArray,0,$indextoCheck);
        } else {
            $workingArray=array_slice($workingArray,$indextoCheck+1);
        }
    }
 }