Avoid the performance/memory overheads of "clone on modify" of $args (#1884)

* Avoid the performance/memory overheads of "clone on modify" of $args when building the condition set/database for AVERAGEIFS(), MAXIFS() and MINIFS()
* Avoid the performance/memory overheads of "clone on modify" of $args when building the condition set/database for COUNTIFS()
This commit is contained in:
Mark Baker 2021-02-27 23:10:33 +01:00 committed by GitHub
parent 80a20fc991
commit 761c84a946
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 45 additions and 31 deletions

View File

@ -67,8 +67,8 @@ class Conditional
return self::AVERAGEIF($args[2], $args[1], $args[0]);
}
$conditions = self::buildConditionSet(...$args);
$database = self::buildDatabase(...$args);
$conditions = self::buildConditionSetForRange(...$args);
$database = self::buildDatabaseWithRange(...$args);
return DAverage::evaluate($database, self::VALUE_COLUMN_NAME, $conditions);
}
@ -122,19 +122,8 @@ class Conditional
return self::COUNTIF(...$args);
}
$conditions = $database = [];
$pairCount = 1;
while (count($args) > 0) {
$conditions[] = array_merge([sprintf(self::CONDITIONAL_COLUMN_NAME, $pairCount)], [array_pop($args)]);
$database[] = array_merge(
[sprintf(self::CONDITIONAL_COLUMN_NAME, $pairCount)],
Functions::flattenArray(array_pop($args))
);
++$pairCount;
}
$conditions = array_map(null, ...$conditions);
$database = array_map(null, ...$database);
$database = self::buildDatabase(...$args);
$conditions = self::buildConditionSet(...$args);
return DCount::evaluate($database, null, $conditions);
}
@ -157,8 +146,8 @@ class Conditional
return 0.0;
}
$conditions = self::buildConditionSet(...$args);
$database = self::buildDatabase(...$args);
$conditions = self::buildConditionSetForRange(...$args);
$database = self::buildDatabaseWithRange(...$args);
return DMax::evaluate($database, self::VALUE_COLUMN_NAME, $conditions);
}
@ -181,24 +170,23 @@ class Conditional
return 0.0;
}
$conditions = self::buildConditionSet(...$args);
$database = self::buildDatabase(...$args);
$conditions = self::buildConditionSetForRange(...$args);
$database = self::buildDatabaseWithRange(...$args);
return DMin::evaluate($database, self::VALUE_COLUMN_NAME, $conditions);
}
private static function buildConditionSet(...$args): array
{
array_shift($args);
$conditions = self::buildConditions(1, ...$args);
$conditions = [];
$pairCount = 1;
while (count($args) > 0) {
$conditions[] = array_merge([sprintf(self::CONDITIONAL_COLUMN_NAME, $pairCount)], [array_pop($args)]);
array_pop($args);
++$pairCount;
return array_map(null, ...$conditions);
}
private static function buildConditionSetForRange(...$args): array
{
$conditions = self::buildConditions(2, ...$args);
if (count($conditions) === 1) {
return array_map(
function ($value) {
@ -211,20 +199,46 @@ class Conditional
return array_map(null, ...$conditions);
}
private static function buildConditions(int $startOffset, ...$args): array
{
$conditions = [];
$pairCount = 1;
$argumentCount = count($args);
for ($argument = $startOffset; $argument < $argumentCount; $argument += 2) {
$conditions[] = array_merge([sprintf(self::CONDITIONAL_COLUMN_NAME, $pairCount)], [$args[$argument]]);
++$pairCount;
}
return $conditions;
}
private static function buildDatabase(...$args): array
{
$database = [];
return self::buildDataSet(0, $database, ...$args);
}
private static function buildDatabaseWithRange(...$args): array
{
$database = [];
$database[] = array_merge(
[self::VALUE_COLUMN_NAME],
Functions::flattenArray(array_shift($args))
Functions::flattenArray($args[0])
);
return self::buildDataSet(1, $database, ...$args);
}
private static function buildDataSet(int $startOffset, array $database, ...$args): array
{
$pairCount = 1;
while (count($args) > 0) {
array_pop($args);
$argumentCount = count($args);
for ($argument = $startOffset; $argument < $argumentCount; $argument += 2) {
$database[] = array_merge(
[sprintf(self::CONDITIONAL_COLUMN_NAME, $pairCount)],
Functions::flattenArray(array_pop($args))
Functions::flattenArray($args[$argument])
);
++$pairCount;
}