myPatterns/JS can be integrated with JSONQuery, as shown by a prototype called myJSONQuery/JS, demonstrated below with a few examples.
var arr1 = [{a:{a:1, b:2, c:1}, b:2, c:2}, {a:1, b:2, c:3}, {a:1, b:2}]; JSONQuery('..[?(a=1 & b=2)]', arr1);Result:
The same query can be written in myJSONQuery using the ~? operator with the JSON pattern "{a:1, b:2}", instead of the ? operator with the equivalent boolean expression (a=1 & b=2):
JSONQuery('..[~?"{a:1,b:2}"]', arr1);
In this case, the two queries are very similar, so using patterns or predicates is really a matter of personal taste.
However, consider the following pattern query, selecting all the elements containing a field b with value 2 and fields a and c having any value:
JSONQuery('..[~?"{a:%x,b:2,c:%y}"]', arr1);Result:
(The printed form includes some references because the structure {a:1, b:2, c:1} occurs both as a sub-data embedded in the first top-level value and as a top-level value in the selection: the second value.)
At first sight, the equivalent non-pattern query is shorter than that:
JSONQuery('..[?(b=2)]', arr1);Result:
Ooops! As we can see from the different result, the above JSONQuery is not strictly equivalent to the previous pattern query, as it also selects objects having field c undefined! The strictly equivalent JSONQuery is in fact the following:
JSONQuery('..[?(a!=undefined & b=2 & c!=undefined)]', arr1);which is already longer and less elegant than the pattern-based one above.
Result:
For example, the following pattern query selects the same objects as above, but extracts from each the value of the fields a and c:
JSONQuery('..[~="{a:%x,b:2,c:%y}"]', arr1);Result:
In this case, the equivalent JSONQuery without patterns is considerably longer, because the JSON pattern both filters some structures and extracts some sub-data thereof. These two steps have to be explicited in the pure JSONQuery:
JSONQuery('..[?(a!=undefined & b=2 & c!=undefined)][={x:@.a, y:@.c}]', arr1);Result:
As can be seen, pattern matching queries in myJSONQuery can be simpler (or even significantly simpler) than their equivalent non-pattern forms, because a JSON pattern may combine selection and extraction operations.
Consider for instance the following recursive array, and the following pattern query extracting all its non-empty sub-arrays (the "[%x|%y]" notation means an array whose first element is x and whose rest is y):
var arr2 = [[1], 2, [3,[4,5]]]; JSONQuery('[~?"[%x|%y]"]', arr2);Result:
The equivalent non-pattern query is as follows:
JSONQuery('[?(@[0]!=undefined)]', arr2);Result:
As can be seen, the pattern form is slightly more concise and more readable.
But, as in the previous section, patterns become more interesting when used to extract sub-data, like in the following pattern query:
JSONQuery('[~="[%x|%y]"]', arr2);Result:
In this case, the equivalent non-pattern query is considerably longer:
JSONQuery('[?(@[0]!=undefined)][={x:@[0], y:@.slice(1)}]', arr2);Result:
This custom notation can easily be defined in myPatterns/JS as follows :
// definition of a Rectangle object function Rectangle(x, y, w, h) { this.xpos = x; this.ypos = y; this.width = w; this.height = h; } // definition of its custom notation: Rectangle.prototype.matches = function(pat, off, acc) { off = matchToken("[", pat, off); off = matchData(this.width, pat, off, acc); off = matchToken("x", pat, off); off = matchData(this.height, pat, off, acc); off = matchToken("+", pat, off); off = matchData(this.xpos, pat, off, acc); off = matchToken("+", pat, off); off = matchData(this.ypos, pat, off, acc); return matchToken("]", pat, off); };That's all! Now we are able to write pattern queries over an array of window objects such as the following two queries, which select from the array below all the windows of size 300x200 pixels, and respectively extract some data thereof:
var windows = [ new Rectangle(100, 50, 300, 200), new Rectangle(200, 350, 300, 200), new Rectangle(400, 650, 300, 200), new Rectangle(600, 50, 200, 100) ]; JSONQuery('[~?"[300x200+%w+%h]"]', windows);Result:
JSONQuery('[~="[300x200+%w+%h]"]', windows);Result:
JSONQuery('[~="[300x200+%w+%h]"][?(h>100)][\\h,/w]', windows);Result: