json-logic-js
json-logic-js copied to clipboard
Change the reduce function to evaluate the initial value
Change the reduce function to evaluate the initial value, which lets us capture state for use in the logic function.
Normally, when we iterate through elements in a reduce function, we only have access to that one element. We aren't able to capture any state from outside.
For example, if I have a list of elements, and want to know which are more than 2, I can do the following:
jsonLogic.apply({
"reduce": [
[1, 2, 3, 4, 5],
{ "+": [{ "if": [{ ">": [{ "var": "current" }, 2] }, 1, 0] }, { "var": "accumulator" }] },
0
]
}); // 3
However, if I want to be able to set the threshold of 2 based on data, I am unable to access that within the reduce.
Reworking this, so that I can pass both the initial count and the goal in the accumulator by having the initial value be an array with the count and the threshold, I can do:
jsonLogic.apply({
"reduce": [
[1, 2, 3, 4, 5],
[
{ "+": [{ "if": [{ ">": [{ "var": "current" }, { "var": "accumulator.1" }] }, 1, 0] }, { "var": "accumulator.0" }] },
{ "var": "accumulator.1" }
],
[0, 2]
]
}); // [3, 2]
If I want to provide the threshold in the data portion, things don't work as expected, since the initial value is not applied.
jsonLogic.apply({
"reduce": [
[1, 2, 3, 4, 5],
[
{ "+": [{ "if": [{ ">": [{ "var": "current" }, { "var": "accumulator.1" }] }, 1, 0] }, { "var": "accumulator.0" }] },
{ "var": "accumulator.1" }
],
[0, {"var": "threshold"}]
]
}, {"threshold": 2}); // [0, {var: "threshold"}]
With this change, the initial value will be evaluated, so we get the expected answer of [3, 2]
.