我有一个PHP脚本,它读取大型CSV并执行某些操作,但前提是“用户名”字段是唯一的。 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()
更有效的搜索方式,考虑到它可能不知道数组是否已排序?
答案 0 :(得分: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 :(得分:4)
以排序顺序从头开始构建数组的方法是插入排序。在PHP-ish伪代码中:
$list = []
for ($element in $elems_to_insert) {
$index = binary_search($element, $list);
insert_into_list($element, $list, $index);
}
虽然,实际上可能会更快地以未排序的顺序创建数组,然后使用quicksort(PHP的内置排序函数使用quicksort)
并在排序列表中查找元素:
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
。
答案 2 :(得分:1)
php中的数组类型是有序映射(php array type)。如果你将int或字符串作为键传入,你将有一个有序的地图......
请查看以上链接中的第6项。
答案 3 :(得分:0)
in_array()不会受益于排序数组。 PHP只是沿着整个数组走,好像它是一个链表。