title: Porters Stemming Algorithm Javascript, How to
body: <p>Below is Porters Stemming Algorithm for JavaScript which I have taken from here:  <a href="http://tartarus.org/~martin/PorterStemmer/js.txt" rel="nofollow">http://tartarus.org/~martin/PorterStemmer/js.txt</a></p>
  
  <p>I would like to be able to use the algorithm by simply calling:</p>
  
  <pre><code>var stemmed_word = porter_stemming_alg( "some_word_to_stem" );
  </code></pre>
  
  <p>Does anyone have any suggestions as to how I would incorporate this functionality into the code below??</p>
  
  <p>Something along the lines of:</p>
  
  <pre><code>function porter_stemming_alg( word ){
      //...
      // algorithm goes here...
      //...
  }
  </code></pre>
  
  <p>Any suggestions appreciated guys....</p>
  
  <pre><code>var stemmer = (function(){
  var step2list = {
          "ational" : "ate",
          "tional" : "tion",
          "enci" : "ence",
          "anci" : "ance",
          "izer" : "ize",
          "bli" : "ble",
          "alli" : "al",
          "entli" : "ent",
          "eli" : "e",
          "ousli" : "ous",
          "ization" : "ize",
          "ation" : "ate",
          "ator" : "ate",
          "alism" : "al",
          "iveness" : "ive",
          "fulness" : "ful",
          "ousness" : "ous",
          "aliti" : "al",
          "iviti" : "ive",
          "biliti" : "ble",
          "logi" : "log"
      },
  
      step3list = {
          "icate" : "ic",
          "ative" : "",
          "alize" : "al",
          "iciti" : "ic",
          "ical" : "ic",
          "ful" : "",
          "ness" : ""
      },
  
      c = "[^aeiou]",          // consonant
      v = "[aeiouy]",          // vowel
      C = c + "[^aeiouy]*",    // consonant sequence
      V = v + "[aeiou]*",      // vowel sequence
  
      mgr0 = "^(" + C + ")?" + V + C,               // [C]VC... is m&gt;0
      meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$",  // [C]VC[V] is m=1
      mgr1 = "^(" + C + ")?" + V + C + V + C,       // [C]VCVC... is m&gt;1
      s_v = "^(" + C + ")?" + v;                   // vowel in stem
  
  return function (w) {
      var     stem,
          suffix,
          firstch,
          re,
          re2,
          re3,
          re4,
          origword = w;
  
      if (w.length &lt; 3) { return w; }
  
      firstch = w.substr(0,1);
      if (firstch == "y") {
          w = firstch.toUpperCase() + w.substr(1);
      }
  
      // Step 1a
      re = /^(.+?)(ss|i)es$/;
      re2 = /^(.+?)([^s])s$/;
  
      if (re.test(w)) { w = w.replace(re,"$1$2"); }
      else if (re2.test(w)) { w = w.replace(re2,"$1$2"); }
  
      // Step 1b
      re = /^(.+?)eed$/;
      re2 = /^(.+?)(ed|ing)$/;
      if (re.test(w)) {
          var fp = re.exec(w);
          re = new RegExp(mgr0);
          if (re.test(fp[1])) {
              re = /.$/;
              w = w.replace(re,"");
          }
      } else if (re2.test(w)) {
          var fp = re2.exec(w);
          stem = fp[1];
          re2 = new RegExp(s_v);
          if (re2.test(stem)) {
              w = stem;
              re2 = /(at|bl|iz)$/;
              re3 = new RegExp("([^aeiouylsz])\\1$");
              re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
              if (re2.test(w)) {  w = w + "e"; }
              else if (re3.test(w)) { re = /.$/; w = w.replace(re,""); }
              else if (re4.test(w)) { w = w + "e"; }
          }
      }
  
      // Step 1c
      re = /^(.+?)y$/;
      if (re.test(w)) {
          var fp = re.exec(w);
          stem = fp[1];
          re = new RegExp(s_v);
          if (re.test(stem)) { w = stem + "i"; }
      }
  
      // Step 2
      re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
      if (re.test(w)) {
          var fp = re.exec(w);
          stem = fp[1];
          suffix = fp[2];
          re = new RegExp(mgr0);
          if (re.test(stem)) {
              w = stem + step2list[suffix];
          }
      }
  
      // Step 3
      re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
      if (re.test(w)) {
          var fp = re.exec(w);
          stem = fp[1];
          suffix = fp[2];
          re = new RegExp(mgr0);
          if (re.test(stem)) {
              w = stem + step3list[suffix];
          }
      }
  
      // Step 4
      re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
      re2 = /^(.+?)(s|t)(ion)$/;
      if (re.test(w)) {
          var fp = re.exec(w);
          stem = fp[1];
          re = new RegExp(mgr1);
          if (re.test(stem)) {
              w = stem;
          }
      } else if (re2.test(w)) {
          var fp = re2.exec(w);
          stem = fp[1] + fp[2];
          re2 = new RegExp(mgr1);
          if (re2.test(stem)) {
              w = stem;
          }
      }
  
      // Step 5
      re = /^(.+?)e$/;
      if (re.test(w)) {
          var fp = re.exec(w);
          stem = fp[1];
          re = new RegExp(mgr1);
          re2 = new RegExp(meq1);
          re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
          if (re.test(stem) || (re2.test(stem) &amp;&amp; !(re3.test(stem)))) {
              w = stem;
          }
      }
  
      re = /ll$/;
      re2 = new RegExp(mgr1);
      if (re.test(w) &amp;&amp; re2.test(w)) {
          re = /.$/;
          w = w.replace(re,"");
      }
  
      // and turn initial Y back to y
  
      if (firstch == "y") {
          w = firstch.toLowerCase() + w.substr(1);
      }
  
      return w;
  }
  })();
  </code></pre>