快速搜索php中的多维数组

时间:2015-05-07 18:15:57

标签: php arrays multidimensional-array

我有一个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),
);

这花费了太多时间,我怎样才能让它跑得更快?

如果我将第一个文件存储到数据库然后进行比较会不会更好?

3 个答案:

答案 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