scan()

The scan linq operator returns a new linq operator that contains the same number of elements as the initial collection where the N-th element of the results is the aggregation of given 'operation' performed on the first N elements of the initial collection. The 'operation' parameter should be a commutative binary operation (e.g., addition, multiplication, etc.).

The scan operator will throw an exception if the operation is not given.

That is the technical explanation--but what does the scan operator really do?

Say that you have an array of integers that you want to add together:

var arr = [1, 2, 3, 4, 5];
You might write an imperative function to sum the numbers:

function sumArray(arr)
{
    var total = 0;
    
    for (var i = 0; i < arr.length; i++)
    {
        total += arr[i];
    }
    
    return total;
}
Executing this function on the array would give you the correct answer of 15. But now let's say that you wanted to see the intermediate results of the executing the loop in the function; that is:

Loop Variable, i Value of arr[i] Value of 'total'
0 1 1
1 2 3 (i.e., 1 + 2}
2 3 6 (i.e., 1 + 2 + 3)
3 4 10 (i.e., 1 + 2 + 3 + 4)
4 5 15 (i.e., 1 + 2 + 3 + 4 + 5)

If you used the scan operator on the initial array:

// results = [1, 3, 6, 10, 15]
var results = $linq(arr).scan("(x, y) => x + y").toArray();
Then, the results would be the same as the third column of the table--the value of the 'total' variable with each iteration of the for loop in the sumArray function.

prescan()

The prescan linq operator returns a new linq operator that contains the same number of elements as the initial collection where the N-th element of the results is the aggregation of given 'operation' performed on the first (N-1) elements of the initial collection, except for the first element of the results, which will be set to the value of the 'identity' parameter. The 'operation' parameter should be a commutative binary operation (e.g., addition, multiplication, etc.).

So, what does the prescan operator really do?

Let's take the table from the example for the scan operator, above, and add another column:

Loop Variable, i Value of arr[i] Value of 'total' Value of 'total' before adding arr[i]
0 1 1 0
1 2 3 (i.e., 1 + 2} 1
2 3 6 (i.e., 1 + 2 + 3) 3 (i.e., 1 + 2)
3 4 10 (i.e., 1 + 2 + 3 + 4) 6 (i.e., 1 + 2 + 3)
4 5 15 (i.e., 1 + 2 + 3 + 4 + 5) 10 (i.e., 1 + 2 + 3 + 4)

If you used the prescan operator on the initial array:

// results = [0, 1, 3, 6, 10]
// Note: the second parameter of '0' is the initial value of the 'total' variable in the 
// loop of the sumArray function.
var results = $linq(arr).prescan("(x, y) => x + y", 0).toArray();
Then, the results would be the same as the fourth column of the table--the value of what to add to arr[i] for each iteration of the for loop in the sumArray function to get the corresponding scan element.

Incidentally, if you "zip" (using addition) the initial array with the prescan of the array, you get the same results as scan-ing the initial array.

var arr = [1, 2, 3, 4, 5];

// results1 = [0, 1, 3, 6, 10]
var results1 = $linq(arr).prescan("(x, y) => x + y", 0).toArray();

// results2 = [1, 3, 6, 10, 15]
var results2 = $linq(arr).zip(results1, "(x, y) => x + y").toArray();

// results3 = [1, 3, 6, 10, 15]
var results3 = $linq(arr).scan("(x, y) => x + y").toArray();

// results2 == results3

Last edited Dec 5, 2012 at 5:00 AM by battousai999, version 2