我试图找到一个解决方案来加速PHP的过程。 我们在特定页面上遇到执行时间问题。 我们有一个大约10,000行的数组,我们需要在该数组的某些列上应用几个回调函数。
最好的方法和最快的执行可以越过一个数组,只在几列上应用回调。
<?php
$records = [
['id' => 2135, 'first_name' => 'John', 'price' => 1000, 'unit' => 5, 'discount' => 30],
['id' => 3245, 'first_name' => 'Sally', 'price' => 2000, 'unit' => 8, 'discount' => 80],
['id' => 5342, 'first_name' => 'Jane', 'price' => 4000, 'unit' => 5, 'discount' => 34],
['id' => 5623, 'first_name' => 'Peter', 'price' => 1500, 'unit' => 4, 'discount' => 25]
];
function simpleMultiply($value)
{
return $value * 2;
}
$applyToColumn = ['price','unit','discount'];
// $expectedRecords = array_map('simpleMultiply', array_column($records, 'id'));
$expectedRecords = [
['id' => 2135, 'first_name' => 'John', 'price' => 2000, 'unit' => 10, 'discount' => 60],
['id' => 3245, 'first_name' => 'Sally', 'price' => 4000, 'unit' => 16, 'discount' => 160],
['id' => 5342, 'first_name' => 'Jane', 'price' => 8000, 'unit' => 10, 'discount' => 68],
['id' => 5623, 'first_name' => 'Peter', 'price' => 3000, 'unit' => 8, 'discount' => 50]
];
?>
答案 0 :(得分:2)
array_column
是一项昂贵的操作,因为它必须创建一个全新的数组。对不同的列重复调用它会使该费用倍增。我建议你只使用一个简单的foreach
循环。
$expectedRecords = array();
foreach ($records as $r) {
foreach ($applyToColumn as $col) {
$r[$col] = simpleMultiply($r[$col]);
}
$expectedRecords[] = $r;
}
如果您可以修改原始$records
而不是创建新的$expectedRecords
,则可以在第一个foreach
中使用引用。
foreach ($records as &$r) {
foreach ($applyToColumn as $col) {
$r[$col] = simpleMultiply($r[$col]);
}
}
答案 1 :(得分:0)
您可以将结果集包装在iterator(或generator中,它看起来与迭代器非常相似),在将其作为迭代结果返回之前修改当前行,例如
<?php
class Foo extends IteratorIterator {
public function current() {
$rv = parent::current();
if ( $rv ) {
// ... and more checks here ....
// this example just assumes the fields/elements exist
$rv['x'] *= 17;
return $rv;
}
}
}
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'localonly', 'localonly', array(
PDO::ATTR_EMULATE_PREPARES=>false,
PDO::MYSQL_ATTR_DIRECT_QUERY=>false,
PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION
));
setup($pdo);
// the point is not to have the complete result set in memory
// see: e.g. php.net/mysqlinfo.concepts.buffering (or whatever database you use ;-) )
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
$result = new Foo( $pdo->query('SELECT x,y FROM sofoo') );
foreach( $result as $row ) {
echo join(', ', $row), PHP_EOL;
}
function setup($pdo) {
$pdo->exec('
CREATE TEMPORARY TABLE sofoo(
id int auto_increment, # I just throw this in casually....
x int,
y int,
primary key(id)
)
');
$stmt = $pdo->prepare('INSERT INTO sofoo (x,y) VALUES (?,?)');
foreach( range(1,5) as $x ) {
$stmt->execute( array($x, $x*13) );
}
}
或(没有大部分样板,使用生成器 - 并立即调用匿名函数)
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
$result = (function($iter) {
foreach( $iter as $row ) {
$row['x'] *= 17;
yield $row;
}
})($pdo->query('SELECT x,y FROM sofoo') );
foreach( $result as $row ) {
echo join(', ', $row), PHP_EOL;
}
你可以建立这个&#34;系统&#34;任意复杂。也许传递字段名称和函数来修改元素到生成器,如
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
$result = my_generator(
$pdo->query('SELECT x,y FROM sofoo'),
array('x'=>function($e) { return $e*17; })
);
foreach( $result as $row ) {
echo join(', ', $row), PHP_EOL;
}
function my_generator($iter, $modifiers) {
foreach( $iter as $row ) {
foreach( $modifiers as $field=>$func) {
$row[$field] = $func($row[$field]);
}
yield $row;
}
}
或添加一些链接机制,以便多个函数可以修改相同的字段。或者将完整的行传递给函数,以便它们也可以更改结构。或......或......