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:
parent
80a20fc991
commit
761c84a946
|
|
@ -67,8 +67,8 @@ class Conditional
|
||||||
return self::AVERAGEIF($args[2], $args[1], $args[0]);
|
return self::AVERAGEIF($args[2], $args[1], $args[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$conditions = self::buildConditionSet(...$args);
|
$conditions = self::buildConditionSetForRange(...$args);
|
||||||
$database = self::buildDatabase(...$args);
|
$database = self::buildDatabaseWithRange(...$args);
|
||||||
|
|
||||||
return DAverage::evaluate($database, self::VALUE_COLUMN_NAME, $conditions);
|
return DAverage::evaluate($database, self::VALUE_COLUMN_NAME, $conditions);
|
||||||
}
|
}
|
||||||
|
|
@ -122,19 +122,8 @@ class Conditional
|
||||||
return self::COUNTIF(...$args);
|
return self::COUNTIF(...$args);
|
||||||
}
|
}
|
||||||
|
|
||||||
$conditions = $database = [];
|
$database = self::buildDatabase(...$args);
|
||||||
$pairCount = 1;
|
$conditions = self::buildConditionSet(...$args);
|
||||||
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);
|
|
||||||
|
|
||||||
return DCount::evaluate($database, null, $conditions);
|
return DCount::evaluate($database, null, $conditions);
|
||||||
}
|
}
|
||||||
|
|
@ -157,8 +146,8 @@ class Conditional
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$conditions = self::buildConditionSet(...$args);
|
$conditions = self::buildConditionSetForRange(...$args);
|
||||||
$database = self::buildDatabase(...$args);
|
$database = self::buildDatabaseWithRange(...$args);
|
||||||
|
|
||||||
return DMax::evaluate($database, self::VALUE_COLUMN_NAME, $conditions);
|
return DMax::evaluate($database, self::VALUE_COLUMN_NAME, $conditions);
|
||||||
}
|
}
|
||||||
|
|
@ -181,23 +170,22 @@ class Conditional
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$conditions = self::buildConditionSet(...$args);
|
$conditions = self::buildConditionSetForRange(...$args);
|
||||||
$database = self::buildDatabase(...$args);
|
$database = self::buildDatabaseWithRange(...$args);
|
||||||
|
|
||||||
return DMin::evaluate($database, self::VALUE_COLUMN_NAME, $conditions);
|
return DMin::evaluate($database, self::VALUE_COLUMN_NAME, $conditions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function buildConditionSet(...$args): array
|
private static function buildConditionSet(...$args): array
|
||||||
{
|
{
|
||||||
array_shift($args);
|
$conditions = self::buildConditions(1, ...$args);
|
||||||
|
|
||||||
$conditions = [];
|
return array_map(null, ...$conditions);
|
||||||
$pairCount = 1;
|
}
|
||||||
while (count($args) > 0) {
|
|
||||||
$conditions[] = array_merge([sprintf(self::CONDITIONAL_COLUMN_NAME, $pairCount)], [array_pop($args)]);
|
private static function buildConditionSetForRange(...$args): array
|
||||||
array_pop($args);
|
{
|
||||||
++$pairCount;
|
$conditions = self::buildConditions(2, ...$args);
|
||||||
}
|
|
||||||
|
|
||||||
if (count($conditions) === 1) {
|
if (count($conditions) === 1) {
|
||||||
return array_map(
|
return array_map(
|
||||||
|
|
@ -211,20 +199,46 @@ class Conditional
|
||||||
return array_map(null, ...$conditions);
|
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
|
private static function buildDatabase(...$args): array
|
||||||
|
{
|
||||||
|
$database = [];
|
||||||
|
|
||||||
|
return self::buildDataSet(0, $database, ...$args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function buildDatabaseWithRange(...$args): array
|
||||||
{
|
{
|
||||||
$database = [];
|
$database = [];
|
||||||
$database[] = array_merge(
|
$database[] = array_merge(
|
||||||
[self::VALUE_COLUMN_NAME],
|
[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;
|
$pairCount = 1;
|
||||||
while (count($args) > 0) {
|
$argumentCount = count($args);
|
||||||
array_pop($args);
|
for ($argument = $startOffset; $argument < $argumentCount; $argument += 2) {
|
||||||
$database[] = array_merge(
|
$database[] = array_merge(
|
||||||
[sprintf(self::CONDITIONAL_COLUMN_NAME, $pairCount)],
|
[sprintf(self::CONDITIONAL_COLUMN_NAME, $pairCount)],
|
||||||
Functions::flattenArray(array_pop($args))
|
Functions::flattenArray($args[$argument])
|
||||||
);
|
);
|
||||||
++$pairCount;
|
++$pairCount;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue