2009-01-29 80 views
10

我有一个PHP脚本,它读取大量的CSV并执行某些操作,但前提是“用户名”字段是唯一的。 CSV用于多个脚本,因此将输入从CSV更改为仅包含唯一用户名不是一种选择。保存在PHP中排序的数组

非常基本的程序流程(这我想了解一下)是这样的:

$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()

回答

9

没有保持数组的顺序,但这种优化怎么样?我猜测isset()阵列键应该快于in_array()搜索。

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

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

    // do stuff 
    } 
} 
1

php中的数组类型是有序图(php array type)。如果您以键或字符串形式传递密钥,您将拥有有序的地图...

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

+0

你的意思是例子#6?我读到的方式是数组是有序的映射,这不一定等同于排序:它们只是对它们有一个命令。 – nickf 2009-01-29 06:46:59

+0

@nickf:PHP数组是哈希映射,由数组键指示索引。内部订单与访问值无关。 – Tomalak 2009-01-29 07:14:37

+0

好吧,这是有道理的,但这只是数组的关键,对吧?这不会帮助您尝试在数组中找到特定的值。 – nickf 2009-01-31 11:37:58

4

从头开始以排序顺序构建数组的方式是插入排序。在PHP上下的伪代码:

$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

0

in_array()不受益于有排序的数组。 PHP只是遍历整个数组,就好像它是一个链表一样。