Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html>
- <head>
- <title>The Nub of a JavaScript Array</title>
- <meta charset="UTF-8">
- <style type="text/css">
- #out {font-family:Arial,sans-serif;font-size:1.5em;margin-left:2em;}
- </style>
- <script type="text/javascript">
- var A = [1, 1, 3, 2, 4, 3];
- /*
- classic nub idiom is Reverse Polish expression:
- (( A indexOf A) equals index shapeOf A) compress A
- ((A⍳A)=⍳⍴A)/A ==>
- ((1 1 3 2 4 3⍳1 1 3 2 4 3)=⍳⍴1 1 3 2 4 3)/1 1 3 2 4 3
- (0 0 2 3 4 2=⍳6)/1 1 3 2 4 3
- (0 0 2 3 4 2=0 1 2 3 4 5)/1 1 3 2 4 3
- 1 0 1 1 1 0/1 1 3 2 4 3
- 1 3 2 4 Q.E.D.
- In JavaScript using simplified functions with the names of their
- APL counterparts, nub idiom is
- compress( a, equals( indexOf(a, a), index(shapeOf(a)) )
- literally, "compress a by the equals comparison of the indexOf
- A with itself to the index of its own length"
- NOTE: the simplified implementation presented here is very limited
- and offers no exception-handling, but it's small.
- */
- function write(s, out) {document.getElementById(out).innerHTML += s;};
- // Return unique elements of a in order encountered on first axis.
- // APL: (( a ⍳ a ) = ⍳ ⍴ a ) / a (for vectors)
- // nub([1, 1, 3, 2, 4, 3]) returns [1 3 2 4]
- function nub(a) {
- return compress( a, equals( indexOf(a, a), index(a.length) ) );
- };
- // Return integer vector of length n, starting at index origin
- // Returns [0,1,2,...,n-1]
- // APL: ⍳ n (with ⎕IO = 0))
- // index(4] returns [1, 2, 3, 4]
- function index(n) {
- // Initialize return.
- var idx = new Array();
- // Set value.
- for (var i = 0; i < n; i++) {idx.push(i);}
- return idx;
- };
- // Return integer vector of index positions of first occurrences of elements
- // of vector b in vector a, starting at index origin zero. If element not
- // found, value of it index is one greater than length of a.
- // APL: a ⍳ b (dyadic ⍳ with ⎕IO = 0)
- // indexOf([1, 2, 3, 4, 5, 6], [1, 3, 5, 11, 3, 4] returns [0, 2, 4, 7, 2, 3]
- function indexOf(a, b) {
- // How many elements in b.
- var last = b.length;
- // Initialize return.
- var idxs = new Array();
- // For each element in b...
- for (var i = 0; i < last; i++) {
- // ...set current value of index to take io into account.
- var idx = a.length;
- // ...for each element of a...
- for (var j = 0; j < a.length; j++) {
- // ...if current element of b matches current a, set index and...
- // ...exit loop - limited search-&-destroy.
- if (b[i] === a[j]) {
- idx = j;
- break;
- }
- }
- // ...capture value.
- idxs.push(idx);
- }
- return idxs;
- };
- // Return elements of a that correspond to value of true in b by index.
- // APL: b / a OR b ⌿ a for rank-2+ array a
- // compress([1, 2, 3, 4], [true, false, false, true] returns [1, 4]
- function compress(a, b) {
- // Initialize return.
- var newA = new Array();
- // If element of b is true, keep corresponding element of a.
- for (var i = 0; i < a.length; i++) {if (b[i]) newA.push(a[i]);}
- return newA;
- };
- // Return Boolean indicators of whether a and b are equal on an element-wise
- // basis. Return is array of same structure as arguments with true for
- // matches, and false for mismatches. Returns JS true/false values.
- // APL: a = b
- // equals([1 2 3 4], [1 3 3 5]) returns [true, false, true, false]
- function equals(a, b) {
- // Initialize return.
- var isEqual = new Array();
- // For each element of a (and b), assess equality by value.
- for (var i = 0; i < a.length; i++) {
- isEqual.push(a[i] === b[i]);
- }
- return isEqual;
- };
- // Return shape of homogeneous a - if not homogeneous, return -1. Shape is a
- // vector of the length on each axis in axis order, e.g., shape of
- // [1,2,3] is [3], shape of [[1,2,3],[4,5,6]] is [2,3] in APL. For
- // simplified use here, shapeOf(A) is a cover reference for A.length.
- // APL: ⍴ A
- // shapeOf([1, 2, 3, 4]) returns 4
- function shapeOf(a) {return a.length;};
- window.onload = function() {
- var dbr = '<br /><br />';
- write('A is: [' + A + ']' + dbr, 'out');
- write('⍴ A, shapeOf(A) is: [' + shapeOf(A) + ']' + dbr, 'out');
- write('⍳ ⍴ A, index(shapeOf(A)) is: [' + index(shapeOf(A)) + ']' + dbr, 'out');
- write('A ⍳ A, indexOf(A, A)) is: [' + indexOf(A, A) + ']' + dbr, 'out');
- write('(A ⍳ A) = ⍳ ⍴ A, equals(indexOf(A, A), index(shapeOf(A)) is: [' +
- equals(indexOf(A, A), index(shapeOf(A))) + ']' + dbr, 'out'
- );
- write('(( A ⍳ A ) = ⍳ ⍴ A ) / A, compress(a, equals(indexOf(A, A), index(shapeOf(A))) is: [' +
- nub(A) + ']' + dbr, 'out'
- );
- };
- </script>
- </head>
- <body>
- <p id="out"></p>
- </body>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement