natural 0.1.27 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +7 -0
- package/LICENSE.txt +0 -0
- package/Makefile +0 -0
- package/README.md +237 -24
- package/benchmarks/index.js +1 -1
- package/benchmarks/metaphone.js +0 -0
- package/benchmarks/soundex.js +0 -0
- package/examples/classification/basic.js +0 -0
- package/examples/classification/recall.js +0 -0
- package/examples/classification/store.js +0 -0
- package/examples/inflection/count.js +0 -0
- package/examples/inflection/noun.js +0 -0
- package/examples/inflection/noun_attach.js +0 -0
- package/examples/phonetics/compare.js +0 -0
- package/examples/phonetics/sounds_like.js +0 -0
- package/examples/phonetics/tokenize_and_phoneticize.js +0 -0
- package/examples/stemming/stem_corpus.js +0 -0
- package/examples/stemming/stem_word.js +0 -0
- package/examples/tfidf/array_example.js +0 -0
- package/examples/tfidf/multiple_terms.js +0 -0
- package/examples/tfidf/tfidf_example.js +0 -0
- package/index.js +0 -0
- package/io_spec/test_data/tfidf/one +0 -0
- package/io_spec/test_data/tfidf/two +0 -0
- package/io_spec/tfidf_spec.js +0 -0
- package/io_spec/wordnet_spec.js +0 -0
- package/lib/natural/analyzers/sentence_analyzer.js +16 -13
- package/lib/natural/classifiers/bayes_classifier.js +6 -2
- package/lib/natural/classifiers/classifier.js +0 -0
- package/lib/natural/classifiers/logistic_regression_classifier.js +0 -0
- package/lib/natural/distance/dice_coefficient.js +0 -0
- package/lib/natural/distance/jaro-winkler_distance.js +13 -8
- package/lib/natural/distance/levenshtein_distance.js +0 -0
- package/lib/natural/index.js +8 -0
- package/lib/natural/inflectors/count_inflector.js +0 -0
- package/lib/natural/inflectors/form_set.js +0 -0
- package/lib/natural/inflectors/fr/count_inflector.js +0 -0
- package/lib/natural/inflectors/fr/noun_inflector.js +0 -0
- package/lib/natural/inflectors/ja/noun_inflector.js +0 -0
- package/lib/natural/inflectors/noun_inflector.js +0 -0
- package/lib/natural/inflectors/present_verb_inflector.js +1 -0
- package/lib/natural/inflectors/singular_plural_inflector.js +1 -2
- package/lib/natural/ngrams/ngrams.js +45 -8
- package/lib/natural/ngrams/ngrams_zh.js +83 -0
- package/lib/natural/normalizers/normalizer.js +30 -38
- package/lib/natural/normalizers/normalizer_ja.js +26 -8
- package/lib/natural/normalizers/normalizer_no.js +59 -0
- package/lib/natural/phonetics/double_metaphone.js +9 -4
- package/lib/natural/phonetics/metaphone.js +6 -1
- package/lib/natural/phonetics/phonetic.js +0 -0
- package/lib/natural/phonetics/soundex.js +11 -7
- package/lib/natural/spellcheck/spellcheck.js +80 -0
- package/lib/natural/stemmers/lancaster_rules.js +4 -4
- package/lib/natural/stemmers/lancaster_stemmer.js +0 -0
- package/lib/natural/stemmers/porter_stemmer.js +90 -63
- package/lib/natural/stemmers/porter_stemmer_es.js +22 -23
- package/lib/natural/stemmers/porter_stemmer_fr.js +377 -0
- package/lib/natural/stemmers/porter_stemmer_no.js +155 -0
- package/lib/natural/stemmers/porter_stemmer_pt.js +302 -0
- package/lib/natural/stemmers/stemmer.js +0 -0
- package/lib/natural/stemmers/stemmer_fr.js +58 -0
- package/lib/natural/stemmers/stemmer_no.js +61 -0
- package/lib/natural/stemmers/stemmer_pt.js +65 -0
- package/lib/natural/stemmers/token.js +163 -0
- package/lib/natural/tfidf/tfidf.js +50 -19
- package/lib/natural/tokenizers/aggressive_tokenizer.js +0 -0
- package/lib/natural/tokenizers/aggressive_tokenizer_es.js +0 -0
- package/lib/natural/tokenizers/aggressive_tokenizer_fr.js +36 -0
- package/lib/natural/tokenizers/aggressive_tokenizer_nl.js +0 -0
- package/lib/natural/tokenizers/aggressive_tokenizer_no.js +39 -0
- package/lib/natural/tokenizers/aggressive_tokenizer_pt.js +0 -0
- package/lib/natural/tokenizers/regexp_tokenizer.js +0 -0
- package/lib/natural/tokenizers/tokenizer.js +2 -2
- package/lib/natural/tokenizers/treebank_word_tokenizer.js +0 -0
- package/lib/natural/trie/trie.js +47 -0
- package/lib/natural/util/bag.js +50 -0
- package/lib/natural/util/edge_weighted_digraph.js +112 -0
- package/lib/natural/util/longest_path_tree.js +99 -0
- package/lib/natural/util/shortest_path_tree.js +100 -0
- package/lib/natural/util/stopwords.js +0 -0
- package/lib/natural/util/stopwords_fr.js +194 -0
- package/lib/natural/util/stopwords_nl.js +43 -0
- package/lib/natural/util/stopwords_no.js +42 -0
- package/lib/natural/util/stopwords_pt.js +136 -0
- package/lib/natural/util/topological.js +98 -0
- package/lib/natural/wordnet/data_file.js +0 -0
- package/lib/natural/wordnet/index_file.js +0 -0
- package/lib/natural/wordnet/wordnet.js +0 -0
- package/lib/natural/wordnet/wordnet_file.js +0 -0
- package/package.json +2 -2
- package/spec/aggressive_tokenizer_fr_spec.js +101 -0
- package/spec/aggressive_tokenizer_pt_spec.js +0 -0
- package/spec/aggressive_tokenizer_spec.js +0 -0
- package/spec/bayes_classifier_spec.js +12 -0
- package/spec/classifier_spec.js +84 -0
- package/spec/count_inflector_fr_spec.js +0 -0
- package/spec/count_inflector_spec.js +0 -0
- package/spec/dice_coefficient_spec.js +0 -0
- package/spec/double_metaphone_spec.js +10 -1
- package/spec/jaro-winkler_spec.js +0 -0
- package/spec/lancaster_stemmer_spec.js +10 -1
- package/spec/levenshtein_spec.js +0 -0
- package/spec/logistic_regression_classifier_spec.js +0 -0
- package/spec/longest_path_tree_spec.js +102 -0
- package/spec/metaphone_spec.js +10 -0
- package/spec/ngram_spec.js +61 -0
- package/spec/ngram_zh_spec.js +122 -0
- package/spec/normalizer_ja_spec.js +9 -3
- package/spec/normalizer_no_spec.js +111 -0
- package/spec/normalizer_spec.js +26 -5
- package/spec/noun_inflector_fr_spec.js +0 -0
- package/spec/noun_inflector_ja_spec.js +0 -0
- package/spec/noun_inflector_spec.js +0 -0
- package/spec/porter_stemmer_fr_spec.js +101 -0
- package/spec/porter_stemmer_no_spec.js +143 -0
- package/spec/porter_stemmer_pt_spec.js +50 -0
- package/spec/porter_stemmer_spec.js +49 -0
- package/spec/present_verb_inflector_spec.js +3 -0
- package/spec/remove_diacritics_spec.js +31 -0
- package/spec/sentence_analyzer_spec.js +248 -0
- package/spec/shortest_path_tree_spec.js +132 -0
- package/spec/soundex_spec.js +13 -9
- package/spec/spellcheck_spec.js +92 -0
- package/spec/stemmer_token_spec.js +161 -0
- package/spec/test_data/snowball_fr.txt +20402 -0
- package/spec/test_data/snowball_no.txt +20628 -0
- package/spec/test_data/snowball_pt.txt +32016 -0
- package/spec/test_data/tfdif_testcorpus.txt +0 -0
- package/spec/test_data/tfidf_teststopwords.txt +0 -0
- package/spec/test_data/wordnet_mini.sql +0 -0
- package/spec/tfidf_spec.js +153 -28
- package/spec/tokenizer_ja_spec.js +0 -0
- package/spec/treebank_word_tokenizer_spec.js +0 -0
- package/spec/trie_spec.js +27 -3
|
@@ -25,19 +25,19 @@ var Stemmer = require('./stemmer');
|
|
|
25
25
|
// denote groups of consecutive consonants with a C and consecutive vowels
|
|
26
26
|
// with a V.
|
|
27
27
|
function categorizeGroups(token) {
|
|
28
|
-
return token.replace(/[^aeiou]+/g, '
|
|
28
|
+
return token.replace(/[^aeiouy]+y/g, 'CV').replace(/[aeiou]+/g, 'V').replace(/[^V]+/g, 'C');
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
// denote single consonants with a C and single vowels with a V
|
|
32
32
|
function categorizeChars(token) {
|
|
33
|
-
return token.replace(/[^
|
|
33
|
+
return token.replace(/[^aeiouy]y/g, 'CV').replace(/[aeiou]/g, 'V').replace(/[^V]/g, 'C');
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
// calculate the "measure" M of a word. M is the count of VC sequences dropping
|
|
37
37
|
// an initial C if it exists and a trailing V if it exists.
|
|
38
38
|
function measure(token) {
|
|
39
39
|
if(!token)
|
|
40
|
-
|
|
40
|
+
return -1;
|
|
41
41
|
|
|
42
42
|
return categorizeGroups(token).replace(/^C/, '').replace(/V$/, '').length / 2;
|
|
43
43
|
}
|
|
@@ -67,14 +67,12 @@ function attemptReplace(token, pattern, replacement, callback) {
|
|
|
67
67
|
// attempt to replace a list of patterns/replacements on a token for a minimum
|
|
68
68
|
// measure M.
|
|
69
69
|
function attemptReplacePatterns(token, replacements, measureThreshold) {
|
|
70
|
-
var replacement =
|
|
70
|
+
var replacement = token;
|
|
71
71
|
|
|
72
|
-
for(var i = 0; i < replacements.length; i++) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if(replacement)
|
|
77
|
-
break;
|
|
72
|
+
for(var i = 0; i < replacements.length; i++) {
|
|
73
|
+
if(measureThreshold == null || measure(attemptReplace(token, replacements[i][0], replacements[i][1])) > measureThreshold) {
|
|
74
|
+
replacement = attemptReplace(replacement, replacements[i][0], replacements[i][2]) || replacement;
|
|
75
|
+
}
|
|
78
76
|
}
|
|
79
77
|
|
|
80
78
|
return replacement;
|
|
@@ -83,51 +81,73 @@ function attemptReplacePatterns(token, replacements, measureThreshold) {
|
|
|
83
81
|
// replace a list of patterns/replacements on a word. if no match is made return
|
|
84
82
|
// the original token.
|
|
85
83
|
function replacePatterns(token, replacements, measureThreshold) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
84
|
+
return attemptReplacePatterns(token, replacements, measureThreshold) || token;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// TODO: this should replace all of the messy replacement stuff above
|
|
88
|
+
function replaceRegex(token, regex, includeParts, minimumMeasure) {
|
|
89
|
+
var parts;
|
|
90
|
+
var result = '';
|
|
91
|
+
|
|
92
|
+
if(regex.test(token)) {
|
|
93
|
+
parts = regex.exec(token);
|
|
94
|
+
|
|
95
|
+
includeParts.forEach(function(i) {
|
|
96
|
+
result += parts[i];
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if(measure(result) > minimumMeasure) {
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return null;
|
|
90
105
|
}
|
|
91
106
|
|
|
92
107
|
// step 1a as defined for the porter stemmer algorithm.
|
|
93
108
|
function step1a(token) {
|
|
94
|
-
if(token.match(/(ss|i)es$/))
|
|
109
|
+
if(token.match(/(ss|i)es$/)) {
|
|
95
110
|
return token.replace(/(ss|i)es$/, '$1');
|
|
96
|
-
|
|
97
|
-
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if(token.substr(-1) == 's' && token.substr(-2, 1) != 's' && token.length > 2) {
|
|
98
114
|
return token.replace(/s?$/, '');
|
|
99
|
-
|
|
115
|
+
}
|
|
116
|
+
|
|
100
117
|
return token;
|
|
101
118
|
}
|
|
102
119
|
|
|
103
120
|
// step 1b as defined for the porter stemmer algorithm.
|
|
104
121
|
function step1b(token) {
|
|
105
122
|
if(token.substr(-3) == 'eed') {
|
|
106
|
-
|
|
123
|
+
if(measure(token.substr(0, token.length - 3)) > 0)
|
|
107
124
|
return token.replace(/eed$/, 'ee');
|
|
108
125
|
} else {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
126
|
+
var result = attemptReplace(token, /(ed|ing)$/, '', function(token) {
|
|
127
|
+
if(categorizeGroups(token).indexOf('V') >= 0) {
|
|
128
|
+
result = attemptReplacePatterns(token, [['at', '', 'ate'], ['bl', '', 'ble'], ['iz', '', 'ize']]);
|
|
129
|
+
|
|
130
|
+
if(result != token) {
|
|
131
|
+
return result;
|
|
132
|
+
} else {
|
|
133
|
+
if(endsWithDoublCons(token) && token.match(/[^lsz]$/)) {
|
|
134
|
+
return token.replace(/([^aeiou])\1$/, '$1');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if(measure(token) == 1 && categorizeChars(token).substr(-3) == 'CVC' && token.match(/[^wxy]$/)) {
|
|
138
|
+
return token + 'e';
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return token;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return null;
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
if(result) {
|
|
149
|
+
return result;
|
|
150
|
+
}
|
|
131
151
|
}
|
|
132
152
|
|
|
133
153
|
return token;
|
|
@@ -135,44 +155,48 @@ function step1b(token) {
|
|
|
135
155
|
|
|
136
156
|
// step 1c as defined for the porter stemmer algorithm.
|
|
137
157
|
function step1c(token) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
158
|
+
var categorizedGroups = categorizeGroups(token);
|
|
159
|
+
|
|
160
|
+
if(token.substr(-1) == 'y' && categorizedGroups.substr(0, categorizedGroups.length - 1).indexOf('V') > -1) {
|
|
161
|
+
return token.replace(/y$/, 'i');
|
|
141
162
|
}
|
|
142
|
-
|
|
163
|
+
|
|
143
164
|
return token;
|
|
144
165
|
}
|
|
145
166
|
|
|
146
167
|
// step 2 as defined for the porter stemmer algorithm.
|
|
147
168
|
function step2(token) {
|
|
148
|
-
|
|
149
|
-
['izer', 'ize'], ['abli', 'able'], ['alli', 'al'], ['entli', 'ent'], ['eli', 'e'],
|
|
150
|
-
['ousli', 'ous'], ['ization', 'ize'], ['ation', 'ate'], ['ator', 'ate'],['alism', 'al'],
|
|
151
|
-
['iveness', 'ive'], ['fulness', 'ful'], ['ousness', 'ous'], ['aliti', 'al'],
|
|
152
|
-
['iviti', 'ive'], ['biliti', 'ble']], 0);
|
|
169
|
+
token = replacePatterns(token, [['ational', '', 'ate'], ['tional', '', 'tion'], ['enci', '', 'ence'], ['anci', '', 'ance'],
|
|
170
|
+
['izer', '', 'ize'], ['abli', '', 'able'], ['bli', '', 'ble'], ['alli', '', 'al'], ['entli', '', 'ent'], ['eli', '', 'e'],
|
|
171
|
+
['ousli', '', 'ous'], ['ization', '', 'ize'], ['ation', '', 'ate'], ['ator', '', 'ate'],['alism', '', 'al'],
|
|
172
|
+
['iveness', '', 'ive'], ['fulness', '', 'ful'], ['ousness', '', 'ous'], ['aliti', '', 'al'],
|
|
173
|
+
['iviti', '', 'ive'], ['biliti', '', 'ble'], ['logi', '', 'log']], 0);
|
|
174
|
+
|
|
175
|
+
return token;
|
|
153
176
|
}
|
|
154
177
|
|
|
155
178
|
// step 3 as defined for the porter stemmer algorithm.
|
|
156
179
|
function step3(token) {
|
|
157
|
-
return replacePatterns(token, [['icate', 'ic'], ['ative', ''], ['alize', 'al'],
|
|
158
|
-
['iciti', 'ic'], ['ical', 'ic'], ['ful', ''], ['ness', '']], 0);
|
|
180
|
+
return replacePatterns(token, [['icate', '', 'ic'], ['ative', '', ''], ['alize', '', 'al'],
|
|
181
|
+
['iciti', '', 'ic'], ['ical', '', 'ic'], ['ful', '', ''], ['ness', '', '']], 0);
|
|
159
182
|
}
|
|
160
183
|
|
|
161
184
|
// step 4 as defined for the porter stemmer algorithm.
|
|
162
185
|
function step4(token) {
|
|
163
|
-
return
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
['ate', ''], ['iti', ''], ['ous', ''], ['ive', ''],
|
|
167
|
-
['ize', '']], 1);
|
|
186
|
+
return replaceRegex(token, /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/, [1], 1) ||
|
|
187
|
+
replaceRegex(token, /^(.+?)(s|t)(ion)$/, [1, 2], 1) ||
|
|
188
|
+
token;
|
|
168
189
|
}
|
|
169
190
|
|
|
170
191
|
// step 5a as defined for the porter stemmer algorithm.
|
|
171
192
|
function step5a(token) {
|
|
172
|
-
var m = measure(token);
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
193
|
+
var m = measure(token.replace(/e$/, ''));
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
if(m > 1 || (m == 1 && !(categorizeChars(token).substr(-4, 3) == 'CVC' && token.match(/[^wxy].$/)))) {
|
|
198
|
+
token = token.replace(/e$/, '');
|
|
199
|
+
}
|
|
176
200
|
|
|
177
201
|
return token;
|
|
178
202
|
}
|
|
@@ -180,8 +204,7 @@ function step5a(token) {
|
|
|
180
204
|
// step 5b as defined for the porter stemmer algorithm.
|
|
181
205
|
function step5b(token) {
|
|
182
206
|
if(measure(token) > 1) {
|
|
183
|
-
|
|
184
|
-
return token.replace(/ll$/, 'l');
|
|
207
|
+
return token.replace(/ll$/, 'l');
|
|
185
208
|
}
|
|
186
209
|
|
|
187
210
|
return token;
|
|
@@ -190,12 +213,16 @@ function step5b(token) {
|
|
|
190
213
|
var PorterStemmer = new Stemmer();
|
|
191
214
|
module.exports = PorterStemmer;
|
|
192
215
|
|
|
216
|
+
|
|
193
217
|
// perform full stemming algorithm on a single word
|
|
194
218
|
PorterStemmer.stem = function(token) {
|
|
219
|
+
if(token.length < 3) return token;
|
|
195
220
|
return step5b(step5a(step4(step3(step2(step1c(step1b(step1a(token.toLowerCase())))))))).toString();
|
|
196
221
|
};
|
|
197
222
|
|
|
198
223
|
//exports for tests
|
|
224
|
+
PorterStemmer.categorizeGroups = categorizeGroups;
|
|
225
|
+
PorterStemmer.measure = measure;
|
|
199
226
|
PorterStemmer.step1a = step1a;
|
|
200
227
|
PorterStemmer.step1b = step1b;
|
|
201
228
|
PorterStemmer.step1c = step1c;
|
|
@@ -67,7 +67,6 @@ function removeAccent(token) {
|
|
|
67
67
|
return str;
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
-
|
|
71
70
|
// perform full stemming algorithm on a single word
|
|
72
71
|
PorterStemmer.stem = function(token) {
|
|
73
72
|
token = token.toLowerCase();
|
|
@@ -96,7 +95,7 @@ PorterStemmer.stem = function(token) {
|
|
|
96
95
|
if(isVowel(token[1])) {
|
|
97
96
|
// If the second letter is a consonant, RV is the region after the next following vowel
|
|
98
97
|
rv = getNextVowelPos(token, 2) +1;
|
|
99
|
-
} else if (isVowel(token[0]) && isVowel(token[1])) {
|
|
98
|
+
} else if (isVowel(token[0]) && isVowel(token[1])) {
|
|
100
99
|
// or if the first two letters are vowels, RV is the region after the next consonant
|
|
101
100
|
rv = getNextConsonantPos(token, 2) + 1;
|
|
102
101
|
} else {
|
|
@@ -113,41 +112,41 @@ PorterStemmer.stem = function(token) {
|
|
|
113
112
|
var token_orig = token;
|
|
114
113
|
|
|
115
114
|
// Step 0: Attached pronoun
|
|
116
|
-
var pronoun_suf = new Array('me', 'se', 'sela', 'selo', 'selas', 'selos', 'la', 'le', 'lo', 'las', 'les', 'los', 'nos');
|
|
117
|
-
var pronoun_suf_pre1 = new Array('éndo', 'ándo', 'ár', 'ér', 'ír');
|
|
115
|
+
var pronoun_suf = new Array('me', 'se', 'sela', 'selo', 'selas', 'selos', 'la', 'le', 'lo', 'las', 'les', 'los', 'nos');
|
|
116
|
+
var pronoun_suf_pre1 = new Array('éndo', 'ándo', 'ár', 'ér', 'ír');
|
|
118
117
|
var pronoun_suf_pre2 = new Array('ando', 'iendo', 'ar', 'er', 'ir');
|
|
119
118
|
var suf = endsinArr(token, pronoun_suf);
|
|
120
119
|
|
|
121
|
-
|
|
120
|
+
|
|
122
121
|
if (suf!='') {
|
|
123
122
|
|
|
124
123
|
var pre_suff = endsinArr(rv_txt.slice(0,-suf.length),pronoun_suf_pre1);
|
|
125
|
-
|
|
124
|
+
|
|
126
125
|
if (pre_suff != '') {
|
|
127
|
-
|
|
126
|
+
|
|
128
127
|
token = removeAccent(token.slice(0,-suf.length));
|
|
129
128
|
} else {
|
|
130
129
|
var pre_suff = endsinArr(rv_txt.slice(0,-suf.length),pronoun_suf_pre2);
|
|
131
|
-
|
|
130
|
+
|
|
132
131
|
if (pre_suff != '' ||
|
|
133
|
-
(endsin(token, 'yendo' ) &&
|
|
132
|
+
(endsin(token, 'yendo' ) &&
|
|
134
133
|
(token.slice(-suf.length-6,1) == 'u'))) {
|
|
135
134
|
token = token.slice(0,-suf.length);
|
|
136
135
|
}
|
|
137
136
|
}
|
|
138
137
|
}
|
|
139
|
-
|
|
138
|
+
|
|
140
139
|
if (token != token_orig) {
|
|
141
140
|
r1_txt = token.substring(r1-1);
|
|
142
141
|
r2_txt = token.substring(r2-1);
|
|
143
142
|
rv_txt = token.substring(rv-1);
|
|
144
143
|
}
|
|
145
144
|
var token_after0 = token;
|
|
146
|
-
|
|
145
|
+
|
|
147
146
|
if ((suf = endsinArr(r2_txt, new Array('anza', 'anzas', 'ico', 'ica', 'icos', 'icas', 'ismo', 'ismos', 'able', 'ables', 'ible', 'ibles', 'ista', 'istas', 'oso', 'osa', 'osos', 'osas', 'amiento', 'amientos', 'imiento', 'imientos'))) != '') {
|
|
148
|
-
token = token.slice(0, -suf.length);
|
|
147
|
+
token = token.slice(0, -suf.length);
|
|
149
148
|
} else if ((suf = endsinArr(r2_txt, new Array('icadora', 'icador', 'icación', 'icadoras', 'icadores', 'icaciones', 'icante', 'icantes', 'icancia', 'icancias', 'adora', 'ador', 'ación', 'adoras', 'adores', 'aciones', 'ante', 'antes', 'ancia', 'ancias'))) != '') {
|
|
150
|
-
token = token.slice(0, -suf.length);
|
|
149
|
+
token = token.slice(0, -suf.length);
|
|
151
150
|
} else if ((suf = endsinArr(r2_txt, new Array('logía', 'logías'))) != '') {
|
|
152
151
|
token = token.slice(0, -suf.length)+ 'log';
|
|
153
152
|
} else if ((suf =endsinArr(r2_txt, new Array('ución', 'uciones'))) != '') {
|
|
@@ -172,37 +171,37 @@ PorterStemmer.stem = function(token) {
|
|
|
172
171
|
rv_txt = token.substring(rv-1);
|
|
173
172
|
}
|
|
174
173
|
var token_after1 = token;
|
|
175
|
-
|
|
174
|
+
|
|
176
175
|
if (token_after0 == token_after1) {
|
|
177
|
-
// Do step 2a if no ending was removed by step 1.
|
|
176
|
+
// Do step 2a if no ending was removed by step 1.
|
|
178
177
|
if ((suf = endsinArr(rv_txt, new Array('ya', 'ye', 'yan', 'yen', 'yeron', 'yendo', 'yo', 'yó', 'yas', 'yes', 'yais', 'yamos'))) != '' && (token.substring(suf.length-1,1) == 'u')) {
|
|
179
178
|
token = token.slice(0, -suf.length);
|
|
180
179
|
}
|
|
181
|
-
|
|
180
|
+
|
|
182
181
|
if (token != token_after1) {
|
|
183
182
|
r1_txt = token.substring(r1-1);
|
|
184
183
|
r2_txt = token.substring(r2-1);
|
|
185
184
|
rv_txt = token.substring(rv-1);
|
|
186
185
|
}
|
|
187
186
|
var token_after2a = token;
|
|
188
|
-
|
|
189
|
-
// Do Step 2b if step 2a was done, but failed to remove a suffix.
|
|
187
|
+
|
|
188
|
+
// Do Step 2b if step 2a was done, but failed to remove a suffix.
|
|
190
189
|
if (token_after2a == token_after1) {
|
|
191
|
-
|
|
190
|
+
|
|
192
191
|
if ((suf = endsinArr(rv_txt,new Array('en', 'es', 'éis', 'emos'))) != '') {
|
|
193
192
|
token = token.slice(0,-suf.length);
|
|
194
193
|
if (endsin(token, 'gu')) {
|
|
195
194
|
token = token.slice(0,-1);
|
|
196
195
|
}
|
|
197
196
|
} else if ((suf = endsinArr(rv_txt, new Array('arían', 'arías', 'arán', 'arás', 'aríais', 'aría', 'aréis', 'aríamos', 'aremos', 'ará', 'aré', 'erían', 'erías', 'erán', 'erás', 'eríais', 'ería', 'eréis', 'eríamos', 'eremos', 'erá', 'eré', 'irían', 'irías', 'irán', 'irás', 'iríais', 'iría', 'iréis', 'iríamos', 'iremos', 'irá', 'iré', 'aba', 'ada', 'ida', 'ía', 'ara', 'iera', 'ad', 'ed', 'id', 'ase', 'iese', 'aste', 'iste', 'an', 'aban', 'ían', 'aran', 'ieran', 'asen', 'iesen', 'aron', 'ieron', 'ado', 'ido', 'ando', 'iendo', 'ió', 'ar', 'er', 'ir', 'as', 'abas', 'adas', 'idas', 'ías', 'aras', 'ieras', 'ases', 'ieses', 'ís', 'áis', 'abais', 'íais', 'arais', 'ierais', ' aseis', 'ieseis', 'asteis', 'isteis', 'ados', 'idos', 'amos', 'ábamos', 'íamos', 'imos', 'áramos', 'iéramos', 'iésemos', 'ásemos'))) != '') {
|
|
198
|
-
|
|
197
|
+
|
|
199
198
|
token = token.slice(0, -suf.length);
|
|
200
|
-
|
|
199
|
+
|
|
201
200
|
}
|
|
202
201
|
}
|
|
203
202
|
}
|
|
204
203
|
|
|
205
|
-
// Always do step 3.
|
|
204
|
+
// Always do step 3.
|
|
206
205
|
r1_txt = token.substring(r1-1);
|
|
207
206
|
r2_txt = token.substring(r2-1);
|
|
208
207
|
rv_txt = token.substring(rv-1);
|
|
@@ -216,7 +215,7 @@ PorterStemmer.stem = function(token) {
|
|
|
216
215
|
token = token.slice(0,-1);
|
|
217
216
|
}
|
|
218
217
|
}
|
|
219
|
-
|
|
218
|
+
|
|
220
219
|
return removeAccent(token);
|
|
221
220
|
|
|
222
221
|
};
|