我這幾年比較常在做資料處理分析,但是我用的工具不是 R 也不是 Python ,我主要用的是 PHP
主要也是因為寫了好幾年 PHP ,對於 PHP 也比較熟,也知道一些寫法可以讓效能更好
在資料處理上,常會有一個需求,就是我有兩份資料,我想要做條件性的 join ,例如 A 資料是各公司所在縣市資料, B 資料是各公司營業資料
假如我想要 B 資料中只有新北市的資料,寫法可能會是:
$fp = fopen('company_county.csv', 'r');
$match_companies = array();
while ($rows = fgetcsv($fp)) {
list($id, $county) = $rows;
if ($county == '新北市') {
$match_companies[] = $id;
}
}
fclose($fp);
$fp = fopen('company_data.csv', 'r');
while ($rows = fgetcsv($fp)) {
list($id, $data) = $rows;
if (!in_array($id, $match_companies)) {
continue;
}
// 這邊處理只有新北市的公司
}
但是上面的寫法,如果公司數量很多的話,速度可能會很慢,原因是因為 in_array 用的是 binary search ,他要從 $array 找東西的話,array 越大要找越久。
但是這種情況只要稍微改一下寫法,就可以讓速度快超多。
$fp = fopen('company_county.csv', 'r');
$match_companies = array();
while ($rows = fgetcsv($fp)) {
list($id, $county) = $rows;
if ($county == '新北市') {
$match_companies[$id] = true;
}
}
fclose($fp);
$fp = fopen('company_data.csv', 'r');
while ($rows = fgetcsv($fp)) {
list($id, $data) = $rows;
if (!array_key_exists($id, $match_companies)) {
continue;
}
// 這邊處理只有新北市的公司
}
(有變更的部分改成紅色)
改用 array_key_exists 取代 in_array 的話,速度可能可以快好幾倍,原因是 array_key_exists 是直接檢查 key 是否存在,這是 O(1) 的動作,幾乎可以說是秒殺動作。
所以在使用 in_array() 時,可以多想想,如果後面的 array 很大的話,能不能改成 array_key_exists 的寫法。
[Updated]
- Jimmy 有提到也可以用 isset() ,在這邊的 case 的確也可以用 isset() 沒問題,可以少打幾個字。但是我自己的習慣是因為 $a[1] = null; isset($a[1]) 會回傳 false 這個行為常常會讓我搞錯,為了避免踩到這個雷,因此我很久沒使用 isset( ) 了,寧可多打幾個字用 array_key_exists( ) 來減少 isset 踩到雷的機會。
[update