Advertisement
richarduie

nub.js

Mar 13th, 2019
233
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
HTML 6.16 KB | None | 0 0
  1.     <!DOCTYPE html>
  2.     <html>
  3.     <head>
  4.         <title>The Nub of a JavaScript Array</title>
  5.         <meta charset="UTF-8">
  6.         <style type="text/css">
  7.             #out {font-family:Arial,sans-serif;font-size:1.5em;margin-left:2em;}
  8.         </style>
  9.         <script type="text/javascript">
  10.             var A = [1, 1, 3, 2, 4, 3];
  11.             /*
  12.                 classic nub idiom is Reverse Polish expression:
  13.  
  14.                 (( A indexOf A) equals index shapeOf A) compress A
  15.  
  16.                 ((A⍳A)=⍳⍴A)/A ==>
  17.  
  18.                 ((1 1 3 2 4 3⍳1 1 3 2 4 3)=⍳⍴1 1 3 2 4 3)/1 1 3 2 4 3
  19.  
  20.                 (0 0 2 3 4 2=⍳6)/1 1 3 2 4 3
  21.  
  22.                 (0 0 2 3 4 2=0 1 2 3 4 5)/1 1 3 2 4 3
  23.  
  24.                 1 0 1 1 1 0/1 1 3 2 4 3
  25.  
  26.                 1 3 2 4 Q.E.D.
  27.  
  28.  
  29.                 In JavaScript using simplified functions with the names of their
  30.                 APL counterparts, nub idiom is
  31.  
  32.                 compress( a, equals( indexOf(a, a), index(shapeOf(a)) )
  33.  
  34.                 literally, "compress a by the equals comparison of the indexOf
  35.                 A with itself to the index of its own length"
  36.  
  37.                 NOTE: the simplified implementation presented here is very limited
  38.                       and offers no exception-handling, but it's small.
  39.             */
  40.  
  41.             function write(s, out) {document.getElementById(out).innerHTML += s;};
  42.  
  43.             // Return unique elements of a in order encountered on first axis.
  44.             // APL: (( a ⍳ a ) = ⍳ ⍴ a ) / a  (for vectors)
  45.             // nub([1, 1, 3, 2, 4, 3]) returns [1 3 2 4]
  46.             function nub(a) {
  47.                 return compress( a, equals( indexOf(a, a), index(a.length) ) );
  48.             };
  49.  
  50.             // Return integer vector of length n, starting at index origin
  51.             // Returns [0,1,2,...,n-1]
  52.             // APL: ⍳ n  (with ⎕IO = 0))
  53.             // index(4] returns [1, 2, 3, 4]
  54.             function index(n) {
  55.                 // Initialize return.
  56.                 var idx = new Array();
  57.                 // Set value.
  58.                 for (var i = 0; i < n; i++) {idx.push(i);}
  59.                return idx;
  60.            };
  61.  
  62.            // Return integer vector of index positions of first occurrences of elements
  63.            // of vector b in vector a, starting at index origin zero. If element not
  64.            // found, value of it index is one greater than length of a.
  65.            // APL: a ⍳ b  (dyadic ⍳ with ⎕IO = 0)
  66.            // indexOf([1, 2, 3, 4, 5, 6], [1, 3, 5, 11, 3, 4] returns [0, 2, 4, 7, 2, 3]  
  67.            function indexOf(a, b) {
  68.                // How many elements in b.
  69.                var last = b.length;
  70.                // Initialize return.
  71.                var idxs = new Array();
  72.                // For each element in b...
  73.                for (var i = 0; i < last; i++) {
  74.                    // ...set current value of index to take io into account.
  75.                    var idx = a.length;
  76.                    // ...for each element of a...
  77.                    for (var j = 0; j < a.length; j++) {
  78.                        // ...if current element of b matches current a, set index and...
  79.                        // ...exit loop - limited search-&-destroy.
  80.                        if (b[i] === a[j]) {
  81.                            idx = j;
  82.                            break;
  83.                        }
  84.                    }
  85.                    // ...capture value.
  86.                    idxs.push(idx);
  87.                 }
  88.                 return idxs;
  89.            };
  90.  
  91.            // Return elements of a that correspond to value of true in b by index.
  92.            // APL: b / a  OR  b ⌿ a  for rank-2+ array a
  93.            // compress([1, 2, 3, 4], [true, false, false, true] returns [1, 4]
  94.            function compress(a, b) {
  95.                // Initialize return.
  96.                var newA = new Array();
  97.                // If element of b is true, keep corresponding element of a.
  98.                for (var i = 0; i < a.length; i++) {if (b[i]) newA.push(a[i]);}
  99.                return newA;
  100.            };
  101.  
  102.            // Return Boolean indicators of whether a and b are equal on an element-wise
  103.            // basis. Return is array of same structure as arguments with true for      
  104.            // matches, and false for mismatches. Returns JS true/false values.
  105.            // APL: a = b
  106.            // equals([1 2 3 4], [1 3 3 5]) returns [true, false, true, false]
  107.            function equals(a, b) {
  108.                // Initialize return.
  109.                var isEqual = new Array();
  110.                // For each element of a (and b), assess equality by value.
  111.                for (var i = 0; i < a.length; i++) {
  112.                    isEqual.push(a[i] === b[i]);
  113.                }
  114.                return isEqual;
  115.            };
  116.  
  117.            // Return shape of homogeneous a - if not homogeneous, return -1. Shape is a
  118.            // vector of the length on each axis in axis order, e.g., shape of
  119.            // [1,2,3] is [3], shape of [[1,2,3],[4,5,6]] is [2,3] in APL. For
  120.            // simplified use here, shapeOf(A) is a cover reference for A.length.
  121.            // APL: ⍴ A
  122.            // shapeOf([1, 2, 3, 4]) returns 4
  123.            function shapeOf(a) {return a.length;};
  124.  
  125.            window.onload = function() {
  126.                var dbr = '<br /><br />';
  127.  
  128.                 write('A is: [' + A + ']' + dbr, 'out');
  129.                 write('⍴ A, shapeOf(A) is: [' + shapeOf(A) +  ']' + dbr, 'out');
  130.                 write('⍳ ⍴ A, index(shapeOf(A)) is: [' + index(shapeOf(A)) +  ']' + dbr, 'out');
  131.                 write('A ⍳ A, indexOf(A, A)) is: [' + indexOf(A, A) +  ']' + dbr, 'out');
  132.                 write('(A ⍳ A) = ⍳ ⍴ A, equals(indexOf(A, A), index(shapeOf(A)) is: [' +
  133.                     equals(indexOf(A, A), index(shapeOf(A))) +  ']' + dbr, 'out'
  134.                 );
  135.                 write('(( A ⍳ A ) = ⍳ ⍴ A ) / A, compress(a, equals(indexOf(A, A), index(shapeOf(A))) is: [' +
  136.                       nub(A) +  ']' + dbr, 'out'
  137.                 );
  138.             };
  139.         </script>
  140.     </head>
  141.     <body>
  142.         <p id="out"></p>
  143.     </body>
  144.     </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement