pass the current key to reduce filter's callback

This commit is contained in:
ju1ius
2023-01-19 11:01:38 +01:00
committed by Fabien Potencier
parent 9a40f4a18a
commit 4f2f3f814e
4 changed files with 28 additions and 12 deletions
+1
View File
@@ -11,6 +11,7 @@
* Fix optimizing closures callbacks * Fix optimizing closures callbacks
* Add a better exception when getting an undefined constant via `constant` * Add a better exception when getting an undefined constant via `constant`
* Fix `if` nodes when outside of a block and with an empty body * Fix `if` nodes when outside of a block and with an empty body
* Arrow functions passed to the "reduce" filter now accept the current key as a third argument
# 3.4.3 (2022-09-28) # 3.4.3 (2022-09-28)
+5 -5
View File
@@ -4,21 +4,21 @@
The ``reduce`` filter iteratively reduces a sequence or a mapping to a single The ``reduce`` filter iteratively reduces a sequence or a mapping to a single
value using an arrow function, so as to reduce it to a single value. The arrow value using an arrow function, so as to reduce it to a single value. The arrow
function receives the return value of the previous iteration and the current function receives the return value of the previous iteration and the current
value of the sequence or mapping: value and key of the sequence or mapping:
.. code-block:: twig .. code-block:: twig
{% set numbers = [1, 2, 3] %} {% set numbers = [1, 2, 3] %}
{{ numbers|reduce((carry, v) => carry + v) }} {{ numbers|reduce((carry, v, k) => carry + v * k) }}
{# output 6 #} {# output 8 #}
The ``reduce`` filter takes an ``initial`` value as a second argument: The ``reduce`` filter takes an ``initial`` value as a second argument:
.. code-block:: twig .. code-block:: twig
{{ numbers|reduce((carry, v) => carry + v, 10) }} {{ numbers|reduce((carry, v, k) => carry + v * k, 10) }}
{# output 16 #} {# output 18 #}
Note that the arrow function has access to the current context. Note that the arrow function has access to the current context.
+8 -7
View File
@@ -1703,15 +1703,16 @@ function twig_array_reduce(Environment $env, $array, $arrow, $initial = null)
{ {
twig_check_arrow_in_sandbox($env, $arrow, 'reduce', 'filter'); twig_check_arrow_in_sandbox($env, $arrow, 'reduce', 'filter');
if (!\is_array($array)) { if (!\is_array($array) && !$array instanceof \Traversable) {
if (!$array instanceof \Traversable) { throw new RuntimeError(sprintf('The "reduce" filter only works with arrays or "Traversable", got "%s" as first argument.', \gettype($array)));
throw new RuntimeError(sprintf('The "reduce" filter only works with arrays or "Traversable", got "%s" as first argument.', \gettype($array)));
}
$array = iterator_to_array($array);
} }
return array_reduce($array, $arrow, $initial); $accumulator = $initial;
foreach ($array as $key => $value) {
$accumulator = $arrow($accumulator, $value, $key);
}
return $accumulator;
} }
function twig_array_some(Environment $env, $array, $arrow) function twig_array_some(Environment $env, $array, $arrow)
+14
View File
@@ -0,0 +1,14 @@
--TEST--
"reduce" filter passes iterable key to callback
--TEMPLATE--
{% set status_classes = {
'success': 200,
'warning': 400,
'error': 500,
} %}
{{ status_classes|reduce((carry, v, k) => status_code >= v ? k : carry, '') }}
--DATA--
return ['status_code' => 404]
--EXPECT--
warning