【问题标题】:How to quickly find elements in a sorted array如何快速找到已排序数组中的元素
【发布时间】:2014-07-20 16:22:21
【问题描述】:

我是新来的,但已经检查过以前的帖子,虽然很相似,但对于我想要做的事情来说还不够。我有一个包含 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++;
}

原始数组的外观示例(为安全起见更改了一些信息):

 //csvArray 
 Array (
 [0] => Array
    (
        [0] => ABABABAB
        [1] => test.account
        [2] => Chad
        [3] => Moeller
        [4] => chad.moeller@macmillan.com
        [5] => 9/10/2013 9:29 AM
    )

[1] => Array
    (
        [0] => D2L1.Test
        [1] => w40
        [2] => D2L 
        [3] => Test
        [4] => 
        [5] => 10/28/2013 4:24 PM
    )

//ldap multidimensional array
Array (
[count] => 67
[0] => Array
    (
        [uid] => Array
            (
                [count] => 1
                [0] => alackey1
            )

        [0] => uid
        [count] => 1
        [dn] => uid=alackey1,dc=edu
    )

[1] => Array
    (
        [uid] => Array
            (
                [count] => 1
                [0] => blamb3
            )

        [0] => uid
        [count] => 1
        [dn] => uid=blamb3,dc=edu
    )

【问题讨论】:

  • 您可以考虑树(二进制或其他),而不是 LDAP 记录的直接数组。您遇到的低效率是由于每次都从 LDAP 列表的开头开始。使用二叉树,您可以按照 log2(n) 的顺序创建最大数量的 LDAP 记录。而且,如果您随时从 LDAP 树中删除节点,那也会有所帮助。我认为您的性能也不会受到太大影响,因为您目前正在经历对 LDAP 记录进行排序的过程。只需将这种排序替换为加载树即可。
  • 如果有 70k 条记录,要在 LDAP 树中检查的最大记录数为 17。
  • 感谢您的回复。我不熟悉 LDAP 树。如果您能指出我的参考资料或示例,那将是一个很大的帮助。如果可能的话,我还想尽量减少 ldap 调用的数量。谢谢!
  • 使用您当前的 LDAP 记录排序列表,您也可以只进行二分搜索。首先比较中间记录。如果小于中间记录,您的下一个 LDAP 工作列表是 LDAP 阵列的前半部分。然后,再次与中间记录进行比较。重复直到找到或工作的数组长度 = 0。这种方法实际上比使用树更简单。它正在做你现在正在做的事情,但不是每次都从头开始。

标签: php arrays csv multidimensional-array ldap


【解决方案1】:

这里有一些代码可以替换您的内部循环。它使用二进制搜索。 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);
        }
    }
 }

【讨论】:

  • 太好了,谢谢!我不是 CS 专业的,所以我首先将我的大脑包裹在算法上。看起来它会运作良好。我稍后会试一试并发表评论。注意,这个参考说 array_slice 效率低下en.wikibooks.org/wiki/Algorithm_Implementation/Search/…
  • array_slice 本身并不是低效的,但是 wikibooks 参考是正确的,因为为此目的使用 slice 是低效的。他们提供了一个更好的算法,使用两个变量来跟踪所需数组部分的“顶部”和“底部”。他们的版本很不错。
猜你喜欢
  • 2020-12-20
  • 1970-01-01
  • 1970-01-01
  • 2016-09-25
  • 1970-01-01
  • 2016-07-23
  • 1970-01-01
  • 2012-03-22
  • 2020-03-15
相关资源
最近更新 更多