2009-01-29 89 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只是遍歷整個數組,就好像它是一個鏈表一樣。