June 12, 2019
ArrayFilter callback accepts 3 parameters
Comments
(2)
June 12, 2019
ArrayFilter callback accepts 3 parameters
I try to bend the internet to my will.
Newbie 34 posts
Followers: 24 people
(2)

Just a quick post, but I noticed that the ArrayFilter docs on the Adobe site don’t mention that there are 3 parameters passed to the callback. So thought I’d post it in case people didn’t know. The signature of the callback is:

function(item, [,index, array])

The 2 optional ones of index and array were added in ACF11 update 5.

The index can come in handy, here’s some example uses:

a = [1,2,3,4,5,6,7,8,9,10];

result = a.filter(function(el, index) {
    return index % 2;
});
writeDump(result); // [1,3,5,7,9]

In the above example, I’m grabbing all the odd positioned elements from the array. You could use the array slice syntax to do the same, but you may find the ArrayFilter code easier to reason about. For comparison here’s how to do it with the slice syntax.

a = [1,2,3,4,5,6,7,8,9,10];
result = a[::2];
writeDump(result); // [1,3,5,7,9]

Here’s an example which also uses the 3rd optional argument to get the last 5 elements from the array:

a = [1,2,3,4,5,6,7,8,9,10];
result = a.filter(function(el, index, source) {
    return index > source.len() - 5;
});
writeDump(result); // [6,7,8,9,10]

Again, slice syntax gives us a more succinct way to achieve this.

a = [1,2,3,4,5,6,7,8,9,10];
result = a[-5::];    
writeDump(result); // [6,7,8,9,10]

So are these optional arguments of any use at all?

Well you can do things like pick elements where the position is a multiple of 2 or 5 but not both:

a = [1,2,3,4,5,6,7,8,9,10];
result = a.filter(function(el, index) {
    return index % 2 XOR index % 5;
});
writeDump(var=result, label="30"); // [2,4,5,6,8]

Or you may want to remove several elements by position:

a = [1,2,3,4,5,6,7,8,9,10];
removeIndexes = [1,5,8,10];
result = a.filter(function(el, index, source) {
    return removeIndexes.find(index) == 0;
});
writeDump(result); // [2,3,4,6,7,9]

How about looking for repeating adjacent values in an array:

a = [5,1,1,1,2,3,4,4,5];
result = a.filter(function(el, index, source) {
    if (index == source.len()) {
        return false;
    }
    return source[index+1] == el;
});
writeDump(result); // [1,1,4]

Elements where the next value in the sequence is greater than previous value:

a = [1,2,3,1,2,3,4,5];
result = a.filter(function(el, index, source) {
    if (index == source.len()) {
        return false;
    }
    return el < source[index+1];
});
writeDump(result); // [1,2,1,2,3,4]

These may seem like contrived examples, which frankly they are, but I hope they provide some food for thought on how these additional arguments could come in useful.

2 Comments
2023-10-10 10:11:13
2023-10-10 10:11:13

I have found that if you try this:

https://trycf.com/gist/db5dd5f3c42785db11a3aa1aab692459/lucee5?theme=monokai

It errors out, because it cannot access local variable inside the callback? Any ideas, or is this a bug?

Like
()
(1)
>
karma007
's comment
2023-10-10 14:55:32
2023-10-10 14:55:32
>
karma007
's comment

It’s known and expected. You should use var to scope your variables rather than using the local scope.

Like
()
Add Comment