English 中文(简体)
在 PHP 中保持数组排序
原标题:
  • 时间:2009-01-29 06:20:28
  •  标签:

我有一个PHP脚本,它读取一个大型的CSV文件并执行某些操作,但仅当“用户名”字段唯一时才执行。CSV在多个脚本中被使用,因此更改输入以仅包含唯一的用户名不是一个选项。

非常基本的程序流程(我正在思考)是这样的:

$allUsernames = array();
while($row = fgetcsv($fp)) {
    $username = $row[0];
    if (in_array($username, $allUsernames)) continue;
    $allUsernames[] = $username;
    // process this row
}

由于这个CSV文件可能非常庞大,所以让我考虑的是那个in_array。在搜索数组成员时,最理想的情况是数组已经排序,那么您如何从头开始构建一个有序的数组?一旦它被排序,有没有比使用in_array()更有效的搜索方法,考虑到它可能不知道数组已排序?

最佳回答

不保持数组顺序,但这种优化怎么样?我猜测对于数组键来说,isset()应该比in_array()搜索更快。

$allUsernames = array();
while($row = fgetcsv($fp)) {
  $username = $row[0];

  if (isset($allUsernames[$username])) {
    continue;
  } else {
    $allUsernames[$username] = true;

    // do stuff
  }
}
问题回答

从头开始按排序顺序建立数组的方法是插入排序。在PHP-ish伪代码中是:

$list = []
for ($element in $elems_to_insert) {
     $index = binary_search($element, $list);
     insert_into_list($element, $list, $index);
}

虽然这样做可能会更快,但实际上最好是先创建无序的数组,然后使用快速排序(PHP的内置排序函数使用快速排序)。

在已排序列表中找到一个元素:

function binary_search($list, $element) {
    $start = 0;
    $end = count($list);
    while ($end - $start > 1) {
        $mid = ($start + $end) / 2;
        if ($list[$mid] < $element){
            $start = $mid;
        }
        else{
            $end = $mid;
        }
    }
    return $end;
}

通过这种实现,您必须测试$list[$end]以查看它是否是您想要的元素,因为如果元素不在数组中,这将找到应插入该元素的位置。我这样做是为了使它与以前的代码示例一致。如果您想要,您可以在函数本身中检查$list[$end] === $element

PHP 中的数组类型是一个有序映射(PHP 数组类型)。如果您传入整数或字符串作为键,则会得到一个有序映射...

请查看上面链接中的项目#6。

in_array()函数不受排序数组的益处。PHP将整个数组作为链接列表沿着行走。





相关问题
热门标签