优化阵列合并操作

时间:2014-04-28 18:16:20

标签: php arrays performance optimization

我很感激任何帮助。

我有7个单独的数组,大约有。每个数组中有90,000个数字(让我们称之为arrays1-arrays7)。每个数组本身都没有重复的数字。但是,阵列之间可能存在重复。例如,array2没有重复项,但可以使用与arrays3和arrays4相同的数字。

问题: 一旦所有7个阵列合并,我试图识别所有重复3次的数字。

我必须进行1000次计算,需要15分钟,但这不行,因为我必须运行40次 - 代码:

如果您知道其他最适合此类计算的语言,请告知我们。任何扩展建议,如redis或gearman都是有帮助的。

for($kj=1; $kj<=1000; $kj++)
    {
$result=array_merge($files_array1,$files_array2,$files_array3,$files_array4,$files_array5,$files_array6,$files_array7);

$result=array_count_values($result);

$fp_lines = fopen("equalTo3.txt", "w");

foreach($result as $key => $val)
{
    if($result[$key]==3)
    {
    fwrite($fp_lines, $key."\r\n");
    }
}
fclose($fp_lines);
}

我也用字符串尝试了下面的代码,但是array_map调用和array_count值调用需要17分钟:

for($kj=1; $kj<=1000; $kj++)
    {

$result='';

for ($ii = 0; $ii< 7; $ii++) {
    $result .= $files_array[$hello_won[$ii]].'\r\n';
}

$result2=explode("\n",$result);//5mins
$result2=array_map("trim",$result2);//11mins
$result2=array_count_values($result2);//4-6mins

$fp_lines = fopen("equalTo3.txt", "w");

foreach($result2 as $key => $val)
{

    if($result2[$key]==3)
    {
    fwrite($fp_lines, $key."\r\n");
    }
}
fclose($fp_lines);

unset($result2);

/////////////////////////////////////////////// ////

@piumin @ailvenge @scunliffe @ this.lau_ @monocell感谢所有发帖的人!我正在处理你的所有建议,并在我完成所有答案后明天接受答案。非常感谢你!

3 个答案:

答案 0 :(得分:6)

array_merge()在数组中有更多元素的速度要慢得多,因为(来自php.net):

  

如果输入数组具有相同的字符串键,则后面的值   该密钥将覆盖前一个密钥。但是,如果是数组   包含数字键,后面的值不会覆盖原始值   值,但会附加。

     

带有数字键的输入数组中的值将重新编号   在结果数组中从零开始递增键。

所以这个函数实际上是在做一些条件语句。您可以使用正常添加替换数组合并,包括循环(foreach或任何其他)和[]运算符。你可以编写一个模拟array_merge的函数,比如(使用引用不复制数组..):

function imitateMerge(&$array1, &$array2) {
    foreach($array2 as $i) {
        $array1[] = $i;
    }
}

你会看到速度的增加真的很难。

答案 1 :(得分:1)

这可能都错了,请看最后一次修改

我也认为array_merge是问题,但我的建议是实施 一个函数直接计算几个数组中的值而不是先合并。 这取决于你在数组中有多少重叠。如果重叠 非常小,然后这可能不会比合并快得多,但有重要意义 重叠(rand(0, 200000)以填充数组,当我尝试)这将更快。

function arrValues($arrs) {
    $values = array();

    foreach($arrs as $arr) {
        foreach($arr as $key => $val) {
            if(array_key_exists($key, $values)) {
                $values[$val]++;
            } else {
                $values[$val] = 1;
            }
        }
    }
    return $values;
}

var_dump(arrValues(array
    ($files_array1
    ,$files_array2
    ,$files_array3
    ,$files_array4
    ,$files_array5
    ,$files_array6
    ,$files_array7
    )));

在我的机器上计算大约需要0.5秒,然后另外2秒用于打印这些东西。

-edit -

我也不清楚为什么你做同样的事情1000次?阵列是否不同 每次还是什么?说一下这个原因可能会给人们额外的想法...

- 再次编辑 -

经过一番探索之后,我再也不相信array_merge了。你没有 有足够的重叠,从直接计算一切中受益。有你 调查机器上的可用内存?对我来说,将7个阵列与90k元素合并 每个需要约250M。如果你允许php使用这么多内存,我假设你 因为你没有得到任何分配错误,那么问题可能是内存 根本不可用,你会遇到很多页面错误?如果这不是问题那么 在什么样的机器和你使用的PHP版本?我已经测试了你的 5.5和5.4上的原始代码和修复内存问题它也运行在大约0.5秒。那 每次迭代都会介意你。现在如果你在同一个PHP脚本中执行1000次 这需要一段时间。考虑到你每次都分配所有这些内存,更是如此。

我相信你真的应该考虑把东西放在数据库中。鉴于你的数字,你似乎总共有5亿行。这在php中处理得非常多。数据库使其变得简单。

答案 2 :(得分:0)

我建议更换

foreach($result as $key => $val)
{
    if($result[$key]==3)
    {
    fwrite($fp_lines, $key."\r\n");
    }
}

类似

$res = array_keys(array_filter($result, function($val){return $val == 3;}));
fwrite($fp_lines, implode("\r\n", $res));