...
Code Block | ||||
---|---|---|---|---|
| ||||
select when pageviewwovyn url "/archives/" new_temperature foreach [1, 2, 3] setting (x,i) |
The foreach
statement Is an iterator. This statement would execute the entire rule three times with the variable x
bound to 1, 2, and 3 in each successive execution. A second name is optional in the setting
clause. Here, the name i
will be bound to the index of each array element, i.e. 0, 1, and 2 in each successive execution.
The value following the keyword foreach
can be any KRL expression that yields an array or map. If the variable f
were bound to a JSON data structurean array, you could use a pick and JPex loop over the f
like so:
Code Block | ||||
---|---|---|---|---|
| ||||
select when web pageview url "/archives/"re#archives# foreach f.pick("$..store") setting (x) |
To use the foreach
statement with a map, you provide two variables in the setting
clause that will be bound the name and value of that entry in the map:
Code Block | ||||
---|---|---|---|---|
| ||||
select when web pageview url "/archives/"re#archives# foreach {"a" : 1, "b" : 2, "c" : 3} setting (v,n,v) |
This would bind a
, b
, and c
to n
along with 1, 2, and 3 to v
on each successive iteration through the loop.
...
title | Engine Compatibility |
---|
...
.
You can have more than one loop in a rule by simply nesting one foreach
inside another:
Code Block | ||||
---|---|---|---|---|
| ||||
select when web pageview url "/archives/"re#archives# foreach [1, 2, 3] setting (x) foreach ["a", "b", "c"] setting (y) |
...
The entire rule body—everything after the select
—is executed once for every loop. If the rule condition is true, an action is produced, so a rule with a foreach
over a three-element array would produce three actions if the condition were true each time. (Note: KRL optimizes rule preludes by automatically moving expressions that don’t depend on the variable being set in the foreach statement outside the loop during execution so that only those things that really need to be executed multiple times are.)
There is also a guard condition called "on final" that will allow you to execute a postlude statement only on the last iteration of the foreach.
When to Use a Loop
Warning | ||
---|---|---|
| ||
Much of the example code in this section needs to be rewritten; it uses deprecated features like pick() and page:url() only found in the classic pico engine. But, the idea of using a filter instead of a loop is still valid. |
Your instincts might be to use foreach loops in places where it’s less efficient than using implicit looping. To see when you might want to use a JPex instead of a foreach statement let’s walk through an example.
...
Code Block | ||||
---|---|---|---|---|
| ||||
rule using_foreach {
select when web pageview url ".*"
foreach items setting (d)
pre {
h = d.pick("$.header") + " using foreach";
c = d.pick("$.content");
domain = page:url("domain");
}
if(domain eq d.pick("$.page")) then
notify(h,c);
} |
...
Code Block | ||||
---|---|---|---|---|
| ||||
rule using_foreach_with_filter {
select when web pageview url ".*"
foreach items.filter(
function(x) {page:url("domain") eq
x.pick("$.page")})
setting (d)
pre {
h = d.pick("$.header") + " using foreach";
c = d.pick("$.content");
domain = page:url("domain");
}
if(domain eq d.pick("$.page")) then
notify(h,c);
} |
...
Code Block | ||||
---|---|---|---|---|
| ||||
rule without_foreach {
select when web pageview url ".*"
pre {
dom = page:url("domain");
item = site_data.pick(
"$..items[?(@.page eq '"+dom+"')]");
content = item.pick("$..content");
header = item.pick("$..header")
+ " without foreach";
}
if(dom eq item.pick("$..page")) then
notify(header,content);
} |
...
As we’ve seen, foreach
causes the same rule to be fired multiple times in a single ruleset evaluation. Some actions are better suited to use inside a foreach
loop than others. For example, issuing multiple redirect()
actions from a single rule doesn’t usually make sense. But other actions like append()
, replace()
, send_directive()
, and so on are often done over and over with different data. An example illustrates this idea.
...
Code Block | ||||
---|---|---|---|---|
| ||||
rule prepend { select when web pageview where url == "windley.com" foreach replacements.pick("$.replacements") setting (r) pre { sel = r.pick("$.selector"); new_text = r.pick("$.text"); } prepend(sel,new_text); } |
...