我有一个php脚本,它将两个csv文件作为输入,每个包含超过40000的行,在上传两个文件后我将它们转换为数组。现在我有两个具有40000多个元素的多维数组。像这样
Instead of Trigger
现在,我遍历第一个文件数组并在文件二数组中找到相同的元素
$file1 = array(
array('name'=>'A','count'=>10),
array('name'=>'B','count'=>13),
array('name'=>'C','count'=>15),
array('name'=>'D','count'=>12),
array('name'=>'E','count'=>19),
);
$file2 = array(
array('name'=>'A','count'=>34),
array('name'=>'B','count'=>15),
array('name'=>'C','count'=>43),
array('name'=>'D','count'=>65),
array('name'=>'E','count'=>98),
);
这花费了太多时间,我怎样才能让它跑得更快?
如果我将第一个文件存储到数据库然后进行比较会不会更好?
答案 0 :(得分:0)
如果不试图解决它,我就无法入睡。
我现在没有哈希这个名字。由于碰撞问题和名称字段的唯一性,我使用一个简单的整数索引作为主键。
我真的不知道它有多快。我不得不使用array_keys
来查找给定名称的索引,我认为这是瓶颈。如果您100%保证$file1
中的名称与$file2
中的名称完全相同(数组中相同位置的相同名称),则可以替换array_keys
内容并获取索引而是当前的数组。 (我希望你知道我的意思)
$file1 = array(
array('name'=>'A','count'=>10),
array('name'=>'B','count'=>13),
array('name'=>'C','count'=>15),
array('name'=>'D','count'=>12),
array('name'=>'E','count'=>19),
);
$file2 = array(
array('name'=>'A','count'=>34),
array('name'=>'B','count'=>15),
array('name'=>'C','count'=>43),
array('name'=>'D','count'=>65),
array('name'=>'E','count'=>98),
);
$executer = new executer();
$executer->init($file2);
$out = $executer->work($file1);
echo "<pre>";
print_r($out);
echo "</pre>";
class executer {
private $name_map = array();
private $count_map = array();
private $output = array();
function init($base_array) {
$idx = 0;
foreach($base_array as $a) {
$this->name_map[$idx] = $a['name'];
$this->count_map[$idx] = $a['count'];
$idx++;
}
}
function work($compare_array) {
foreach($compare_array as $c) {
if(!in_array($c['name'], $this->name_map)) {
continue;
}
$keys = array_keys($this->name_map, $c['name']);
if(count($keys) !== 1) {
throw new Exception("This should not happen");
}
$idx = $keys[0];
$file1_count = $this->count_map[$idx];
$count = $c['count']/(1+$file1_count);
$this->output[] = array('name'=>$this->name_map[$idx], 'count'=>$count);
}
return $this->output;
}
}
答案 1 :(得分:0)
我不知道您在阅读CSV文件时所做的事情,但您的姓名字段的值包含特殊字符这一事实并没有什么区别 - 他们可以仍然用作关联数组中的键。你应该做这样的事情:
function readCsv($file,$indexName,$indexCount)
{
$ret=array();
$fh=fopen($file,"r");
while (($data=fgetcsv($fh,1000))!==FALSE)
{
if (count($data)==1 && $data[0]===NULL)
continue; // blank line
$ar=array($data[$indexName]=>$data[$indexCount]);
$ret[]=$ar;
}
fclose($fh);
return $ret;
}
$file1_array=readCsv("file1.csv",0,1); // name in first column, count in second
$file2_array=readCsv("file2.csv",3,2); // name in 4th column, count in 3rd
$output=array();
foreach ($file1_array as $name=>$count)
{
if (array_key_exists($name,$file2_array))
$count=$file2_array[$name]/(1+$count);
else $count=0;
$output[]=array('name'=>$name,'count'=>$count);
}
显然,您需要添加错误检查代码,尤其是在readCsv()
函数中,但这应该会为您提供所需的结果。
请注意,if ... else
可以重写为:
$count=array_key_exists($name,$file2_array) ? $file2_array[$name]/(1+$count) : 0;
以下代码应向您确认非 - &#34;常规&#34;字符可用于数组键值:
$arr=array();
for ($cnt=1; $cnt<10; $cnt++)
$arr[sprintf('ab1%c',$cnt+0x80)]=$cnt;
$str=sprintf('ab1%c',0x83);
for ($cnt=0; $cnt<4; $cnt++)
{
$chr=$str[$cnt];
echo '$str['.$cnt.'] = "'.$str[$cnt].'" = '.sprintf('0x%02x',ord($chr))."\n";
}
var_dump(str_split($str));
echo 'Valid key '.(array_key_exists($str,$arr) ? 'exists' : 'does not exist')."\n";
$str=sprintf('ab1%c',0x8f);
echo 'Invalid key '.(array_key_exists($str,$arr) ? 'exists' : 'does not exist')."\n";
输出:
$str[0] = "a" = 0x61
$str[1] = "b" = 0x62
$str[2] = "1" = 0x31
$str[3] = "?" = 0x83
array(4) {
[0]=>
string(1) "a"
[1]=>
string(1) "b"
[2]=>
string(1) "1"
[3]=>
string(1) "?"
}
Valid key exists
Invalid key does not exist
答案 2 :(得分:0)
我用这个函数把第一个文件作为md5
$control_group = csv_to_array($control_group,$header,true);
$group = csv_to_array($group,$header);
function csv_to_array($file,$header,$md5=false)
{
$csv = array();
if(($file = fopen($file, 'r')) === false)
throw new Exception('There was an error loading the CSV file.');
else
{
fgets($file);
if($md5) {
while (($line = fgetcsv($file, 1000)) !== false)
$csv[md5($line[0])] = $line[1];
} else {
while (($line = fgetcsv($file, 1000)) !== false)
$csv[] = array('name'=>$line[0],'count'=>$line[1]);
}
fclose($file);
}
return $csv;
}
和此功能进行比较
function process($control_group,$group)
{
$output = array();
foreach($group as $element)
{
$control_group_frequency = isset($control_group[md5($element['name'])]) ? $control_group[md5($element['name'])] : 0;
$frequency = round($element['count']/(1+$control_group_frequency),2);
$output[] = array($element['name'],$element['count'],$frequency);
}
return $output;
}
它对我有用。
感谢@steven