chengjie il y a 3 mois
Parent
commit
e45db53d9e
2 fichiers modifiés avec 247 ajouts et 186 suppressions
  1. 36 15
      src/test/build.test32.js
  2. 211 171
      src/util/stringClass.js

+ 36 - 15
src/test/build.test32.js

@@ -2,21 +2,42 @@ import commonModel from '../model/commonModel.js';
2 2
 import fs from 'fs';
3 3
 import { stringUtils } from '../util/stringClass.js';
4 4
 
5
-function runScript(a,b,fuhao){
6
-    if (fuhao=="+")
7
-        return a+b;
8
-    if (fuhao=="-")
9
-        return a-b;
10
-    if (fuhao=="×")
11
-        return a*b;
12
-    if (fuhao=="÷")
13
-        return a/b;
5
+function runScript(){
6
+    check("went");
7
+    check("better");
8
+    check("children");
9
+    check("cannot");
10
+    check("walked");
11
+    check("planned");
12
+    check("used");
13
+    check("studied");
14
+    check("walking");
15
+    check("running");
16
+    check("faster");
17
+    check("fastest");
18
+    check("happier");
19
+    check("happiest");
20
+    check("quickly");
21
+    check("happily");
22
+    check("books");
23
+    check("boxes");
24
+    check("heroes");
25
+    check("cities");
26
+    check("knives");
27
+    check("mice");
28
+    check("this");
29
+    check("WALKED");
30
+    check("can't");
31
+    check("quickly");
32
+    check("run");
33
+    check("big");
34
+    check("computer");
35
+    check("beautiful");
36
+}
14 37
 
15
-    if (fuhao=="²")
16
-        return a*a;
17
-    
38
+function check(str){
39
+    let arr1=stringUtils.getWordAllForms(str);
40
+    console.log(str+" 变形有:"+arr1.join(",")+";\n");
18 41
 }
19 42
 
20
-let a=123,b=456;
21
-let result=runScript(a,b,"²");
22
-console.log(a+"÷"+b+"="+result);
43
+runScript();

+ 211 - 171
src/util/stringClass.js

@@ -1019,9 +1019,6 @@ export const stringUtils = {
1019 1019
         // 保留原始单词,包括大小写和标点符号
1020 1020
         const originalWord = word;
1021 1021
         
1022
-        // 处理缩写词中的撇号
1023
-        const hasApostrophe = word.includes("'");
1024
-        
1025 1022
         // 转换为小写进行处理
1026 1023
         const lowerWord = word.toLowerCase();
1027 1024
         
@@ -1033,47 +1030,41 @@ export const stringUtils = {
1033 1030
             allForms.add(originalWord);
1034 1031
         }
1035 1032
         
1036
-        // 可以考虑添加一个标志来避免重复检查
1037
-        let foundIrregular = false;
1038 1033
         // 检查是否是不规则动词
1039 1034
         for (const [base, forms] of Object.entries(stringUtils.irregularVerbs)) {
1040 1035
             if (base === lowerWord || forms.includes(lowerWord)) {
1041 1036
                 // 添加原形和所有变形
1042 1037
                 allForms.add(base);
1043 1038
                 forms.forEach(form => allForms.add(form));
1044
-                foundIrregular = true;
1045
-                break;
1039
+                // 不规则动词处理完成后继续处理其他类型
1046 1040
             }
1047 1041
         }
1048 1042
         
1049
-        // 不规则形容词/副词检查后应该也考虑是否返回
1043
+        // 不规则形容词/副词检查
1050 1044
         for (const [base, forms] of Object.entries(stringUtils.irregularAdjectives)) {
1051 1045
             if (base === lowerWord || forms.includes(lowerWord)) {
1052 1046
                 // 添加原形和所有变形
1053 1047
                 allForms.add(base);
1054 1048
                 forms.forEach(form => allForms.add(form));
1055
-                foundIrregular = true;
1056
-                break;
1049
+                // 不规则形容词处理完成后继续处理其他类型
1057 1050
             }
1058 1051
         }
1059 1052
 
1060
-        // 不规则名词检查后也应该设置标志
1053
+        // 不规则名词检查(单数形式)
1061 1054
         if (stringUtils.irregularNouns[lowerWord]) {
1055
+            allForms.add(lowerWord); // 添加原词
1062 1056
             stringUtils.irregularNouns[lowerWord].forEach(form => allForms.add(form));
1063
-            foundIrregular = true;
1064 1057
         }
1065 1058
 
1066
-        // 不规则名词复数形式检查后也应该设置标志
1059
+        // 不规则名词检查(复数形式)
1067 1060
         for (const [singular, plurals] of Object.entries(stringUtils.irregularNouns)) {
1068 1061
             if (plurals.includes(lowerWord)) {
1069 1062
                 allForms.add(singular);
1063
+                allForms.add(lowerWord); // 添加原词
1070 1064
                 plurals.forEach(form => allForms.add(form));
1071
-                foundIrregular = true;
1072
-                break;
1073 1065
             }
1074 1066
         }
1075 1067
         
1076
-        // 处理规则变形
1077 1068
         // 特殊处理一些常见的副词和特殊单词,避免错误的词干提取和变形
1078 1069
         const specialWords = {
1079 1070
             // 情态动词
@@ -1083,7 +1074,7 @@ export const stringUtils = {
1083 1074
             'will': ['will', 'would', "won't", "wouldn't"],
1084 1075
             'must': ['must', 'have to', 'has to', 'had to', "mustn't"],
1085 1076
             
1086
-            // 副词
1077
+            // 特殊副词
1087 1078
             'early': ['early', 'earlier', 'earliest'],
1088 1079
             'only': ['only'],
1089 1080
             'likely': ['likely', 'more likely', 'most likely'],
@@ -1115,11 +1106,14 @@ export const stringUtils = {
1115 1106
             'hero': ['hero', 'heroes'],
1116 1107
             'echo': ['echo', 'echoes'],
1117 1108
 
1109
+            // 缩写词
1118 1110
             'its': ['its'], // 物主代词
1119
-            'it\'s': ['it\'s'], // it is 的缩写
1120
-            'I\'m': ['I\'m'], // I am 的缩写
1121
-            'don\'t': ['don\'t'], // do not 的缩写
1122
-            'doesn\'t': ['doesn\'t'], // does not 的缩写
1111
+            'it\'s': ['it\'s', 'it is', 'it has'], // it is 的缩写
1112
+            'I\'m': ['I\'m', 'I am'], // I am 的缩写
1113
+            'don\'t': ['don\'t', 'do not'], // do not 的缩写
1114
+            'doesn\'t': ['doesn\'t', 'does not'], // does not 的缩写
1115
+            'can\'t': ['can\'t', 'cannot'], // can not 的缩写
1116
+            'won\'t': ['won\'t', 'will not'], // will not 的缩写
1123 1117
             'we\'re': ['we are'],
1124 1118
             'they\'re': ['they are'],
1125 1119
             'you\'re': ['you are'],
@@ -1129,14 +1123,25 @@ export const stringUtils = {
1129 1123
             'we\'d': ['we would', 'we had'],
1130 1124
             'they\'d': ['they would', 'they had'],
1131 1125
             'couldn\'t': ['could not'],
1126
+            'shouldn\'t': ['should not'],
1127
+            'wouldn\'t': ['would not'],
1128
+            'mustn\'t': ['must not'],
1129
+            'haven\'t': ['haven\'t', 'have not'],
1130
+            'hasn\'t': ['hasn\'t', 'has not'],
1131
+            'hadn\'t': ['hadn\'t', 'had not'],
1132
+            'isn\'t': ['isn\'t', 'is not'],
1133
+            'aren\'t': ['aren\'t', 'are not'],
1134
+            'wasn\'t': ['wasn\'t', 'was not'],
1135
+            'weren\'t': ['weren\'t', 'were not'],
1132 1136
             'should\'ve': ['should have'],
1133 1137
             'would\'ve': ['would have'],
1134 1138
             'could\'ve': ['could have']
1135 1139
         };
1136 1140
         
1137
-        // 如果是特殊单词,直接返回预定义的变形
1141
+        // 如果是特殊单词,添加预定义的变形
1138 1142
         if (specialWords[lowerWord]) {
1139 1143
             specialWords[lowerWord].forEach(form => allForms.add(form));
1144
+            // 处理完特殊词后返回,避免进一步处理
1140 1145
             return [...allForms];
1141 1146
         }
1142 1147
         
@@ -1144,6 +1149,7 @@ export const stringUtils = {
1144 1149
         for (const [base, forms] of Object.entries(specialWords)) {
1145 1150
             if (forms.includes(lowerWord)) {
1146 1151
                 forms.forEach(form => allForms.add(form));
1152
+                // 处理完特殊词后返回,避免进一步处理
1147 1153
                 return [...allForms];
1148 1154
             }
1149 1155
         }
@@ -1155,156 +1161,176 @@ export const stringUtils = {
1155 1161
         const specialBaseWords = ['this', 'is', 'was', 'has', 'his', 'its', 'us', 'yes', 'thus', 'plus'];
1156 1162
         if (specialBaseWords.includes(lowerWord)) {
1157 1163
             possibleBaseWords.push(lowerWord);
1164
+            // 对于特殊基础词,只返回原词
1158 1165
             return [...allForms];
1159 1166
         }
1160 1167
         
1161 1168
         // 处理规则变形
1162 1169
         // 处理过去式/过去分词 (-ed)
1163
-        if (lowerWord.endsWith('ed')) {
1170
+        if (lowerWord.endsWith('ed') && lowerWord.length > 2) {
1171
+            // 基本形式
1164 1172
             possibleBaseWords.push(lowerWord.slice(0, -2)); // 常规情况 (walked -> walk)
1165 1173
             
1166
-            // 处理双辅音+ed的情况 (stepped -> step, hummed -> hum)
1174
+            // 处理双辅音+ed的情况 (stepped -> step, planned -> plan)
1167 1175
             const doubleConsonantPattern = /([bcdfghjklmnpqrstvwxyz])\1ed$/;
1168 1176
             if (doubleConsonantPattern.test(lowerWord)) {
1169
-                possibleBaseWords.push(lowerWord.slice(0, -3)); // 如 stepped -> step
1177
+                possibleBaseWords.push(lowerWord.slice(0, -3)); // 如 planned -> plan
1170 1178
             }
1171 1179
             
1172
-            // 处理以辅音+e结尾的动词变为ed的情况
1180
+            // 处理以辅音+y结尾变为ied的情况 (studied -> study)
1181
+            if (lowerWord.endsWith('ied') && lowerWord.length > 3) {
1182
+                const beforeY = lowerWord.slice(0, -3);
1183
+                if (beforeY.length > 0 && /[a-z]$/.test(beforeY)) {
1184
+                    possibleBaseWords.push(beforeY + 'y');
1185
+                }
1186
+            }
1187
+            
1188
+            // 处理以e结尾的动词变为ed的情况 (liked -> like)
1173 1189
             if (/[bcdfghjklmnpqrstvwxyz]ed$/.test(lowerWord)) {
1174
-                possibleBaseWords.push(lowerWord.slice(0, -2) + 'e'); // 如 liked -> like
1190
+                possibleBaseWords.push(lowerWord.slice(0, -1)); // 如 liked -> like
1175 1191
             }
1176 1192
         }
1177 1193
         
1178
-        // 处理以e结尾的动词加d的情况
1179
-        if (lowerWord.endsWith('d') && !lowerWord.endsWith('ed')) {
1194
+        // 处理以e结尾的动词加d的情况 (used -> use)
1195
+        if (lowerWord.endsWith('d') && !lowerWord.endsWith('ed') && lowerWord.length > 1) {
1180 1196
             possibleBaseWords.push(lowerWord.slice(0, -1)); // 如 used -> use
1181 1197
         }
1182 1198
         
1183
-        // 处理以辅音+y结尾变为ied的情况
1184
-        if (lowerWord.endsWith('ied')) {
1185
-            possibleBaseWords.push(lowerWord.slice(0, -3) + 'y'); // 如 tried -> try
1186
-            // 处理一些不是由y变形而来的ied结尾单词
1187
-            possibleBaseWords.push(lowerWord.slice(0, -1)); // 如 applied -> apply (虽然这个例子不准确,但为了覆盖更多情况)
1188
-        }
1189
-        
1190 1199
         // 处理现在分词 (-ing)
1191
-        if (lowerWord.endsWith('ing')) {
1200
+        if (lowerWord.endsWith('ing') && lowerWord.length > 3) {
1192 1201
             possibleBaseWords.push(lowerWord.slice(0, -3)); // 常规情况 (walking -> walk)
1193
-            possibleBaseWords.push(lowerWord.slice(0, -3) + 'e'); // 以e结尾的动词 (making -> make)
1194 1202
             
1195
-            // 处理双辅音+ing的情况 (running -> run, swimming -> swim)
1203
+            // 处理双辅音+ing的情况 (running -> run)
1196 1204
             const doubleConsonantPattern = /([bcdfghjklmnpqrstvwxyz])\1ing$/;
1197 1205
             if (doubleConsonantPattern.test(lowerWord)) {
1198 1206
                 possibleBaseWords.push(lowerWord.slice(0, -4)); // 如 running -> run
1199 1207
             }
1200 1208
             
1201
-            // 处理特殊的ing形式
1202
-            if (lowerWord.endsWith('ying')) {
1209
+            // 处理特殊的ing形式 (lying -> lie)
1210
+            if (lowerWord.endsWith('ying') && lowerWord.length > 4) {
1203 1211
                 possibleBaseWords.push(lowerWord.slice(0, -4) + 'ie'); // 如 lying -> lie
1204 1212
             }
1213
+            
1214
+            // 处理以辅音+e结尾的动词变为ing的情况 (like -> liking)
1215
+            if (/[bcdfghjklmnpqrstvwxyz]ing$/.test(lowerWord)) {
1216
+                possibleBaseWords.push(lowerWord.slice(0, -3) + 'e');
1217
+            }
1205 1218
         }
1206 1219
         
1207
-        // 处理比较级/最高级
1208
-        if (lowerWord.endsWith('er')) {
1220
+        // 处理比较级 (-er)
1221
+        if (lowerWord.endsWith('er') && lowerWord.length > 2) {
1209 1222
             possibleBaseWords.push(lowerWord.slice(0, -2)); // 常规情况 (faster -> fast)
1210 1223
             
1211
-            // 处理双辅音+er的情况
1224
+            // 处理双辅音+er的情况 (bigger -> big)
1212 1225
             const doubleConsonantPattern = /([bcdfghjklmnpqrstvwxyz])\1er$/;
1213 1226
             if (doubleConsonantPattern.test(lowerWord)) {
1214 1227
                 possibleBaseWords.push(lowerWord.slice(0, -3)); // 如 bigger -> big
1215 1228
             }
1216 1229
             
1217
-            // 处理以e结尾+r的情况
1230
+            // 处理以辅音+y结尾变为ier的情况 (happier -> happy)
1231
+            if (lowerWord.endsWith('ier') && lowerWord.length > 3) {
1232
+                const beforeY = lowerWord.slice(0, -3);
1233
+                if (beforeY.length > 0 && /[a-z]$/.test(beforeY)) {
1234
+                    possibleBaseWords.push(beforeY + 'y');
1235
+                }
1236
+            }
1237
+            
1238
+            // 处理以e结尾+r的情况 (nicer -> nice)
1218 1239
             if (/[^aeiou]er$/.test(lowerWord)) {
1219
-                possibleBaseWords.push(lowerWord.slice(0, -2) + 'e'); // 如 larger -> large
1240
+                possibleBaseWords.push(lowerWord.slice(0, -2) + 'e'); // 如 nicer -> nice
1220 1241
             }
1221 1242
         }
1222
-        if (lowerWord.endsWith('est')) {
1243
+        
1244
+        // 处理最高级 (-est)
1245
+        if (lowerWord.endsWith('est') && lowerWord.length > 3) {
1223 1246
             possibleBaseWords.push(lowerWord.slice(0, -3)); // 常规情况 (fastest -> fast)
1224 1247
             
1225
-            // 处理双辅音+est的情况
1248
+            // 处理双辅音+est的情况 (biggest -> big)
1226 1249
             const doubleConsonantPattern = /([bcdfghjklmnpqrstvwxyz])\1est$/;
1227 1250
             if (doubleConsonantPattern.test(lowerWord)) {
1228 1251
                 possibleBaseWords.push(lowerWord.slice(0, -4)); // 如 biggest -> big
1229 1252
             }
1230 1253
             
1231
-            // 处理以e结尾+st的情况
1254
+            // 处理以辅音+y结尾变为iest的情况 (happiest -> happy)
1255
+            if (lowerWord.endsWith('iest') && lowerWord.length > 4) {
1256
+                const beforeY = lowerWord.slice(0, -4);
1257
+                if (beforeY.length > 0 && /[a-z]$/.test(beforeY)) {
1258
+                    possibleBaseWords.push(beforeY + 'y');
1259
+                }
1260
+            }
1261
+            
1262
+            // 处理以e结尾+st的情况 (nicest -> nice)
1232 1263
             if (/[^aeiou]est$/.test(lowerWord)) {
1233
-                possibleBaseWords.push(lowerWord.slice(0, -3) + 'e'); // 如 largest -> large
1264
+                possibleBaseWords.push(lowerWord.slice(0, -3) + 'e'); // 如 nicest -> nice
1234 1265
             }
1235 1266
         }
1236 1267
         
1237
-        // 处理以辅音+y结尾变为ier/iest的情况
1238
-        if (lowerWord.endsWith('ier')) {
1239
-            possibleBaseWords.push(lowerWord.slice(0, -3) + 'y'); // 如 happier -> happy
1240
-        }
1241
-        if (lowerWord.endsWith('iest')) {
1242
-            possibleBaseWords.push(lowerWord.slice(0, -4) + 'y'); // 如 happiest -> happy
1243
-        }
1244
-        
1245 1268
         // 处理副词 (-ly)
1246
-        if (lowerWord.endsWith('ly')) {
1269
+        if (lowerWord.endsWith('ly') && lowerWord.length > 2) {
1247 1270
             possibleBaseWords.push(lowerWord.slice(0, -2)); // 常规情况 (quickly -> quick)
1248
-        }
1249
-        
1250
-        // 处理以y结尾变为ily的情况
1251
-        if (lowerWord.endsWith('ily')) {
1252
-            possibleBaseWords.push(lowerWord.slice(0, -3) + 'y'); // 如 happily -> happy
1271
+            
1272
+            // 处理以辅音+y结尾变为ily的情况 (happily -> happy)
1273
+            if (lowerWord.endsWith('ily') && lowerWord.length > 3) {
1274
+                const beforeY = lowerWord.slice(0, -3);
1275
+                if (beforeY.length > 0 && /[a-z]$/.test(beforeY)) {
1276
+                    possibleBaseWords.push(beforeY + 'y');
1277
+                }
1278
+            }
1253 1279
         }
1254 1280
 
1255
-        // 处理复数形式
1256
-        if (lowerWord.endsWith('s') && !lowerWord.endsWith('ss')) {
1257
-            possibleBaseWords.push(lowerWord.slice(0, -1)); // 常规情况 (books -> book)
1258
-        }
1259
-        if (lowerWord.endsWith('es')) {
1260
-            possibleBaseWords.push(lowerWord.slice(0, -2)); // 常规情况 (boxes -> box)
1261
-            
1262
-            // 处理以ch, sh, ss, x, z结尾的名词复数形式
1263
-            if (/(?:ch|sh|ss|x|z)es$/.test(lowerWord)) {
1264
-                possibleBaseWords.push(lowerWord.slice(0, -2)); // 如 boxes -> box, dishes -> dish
1281
+        // 处理复数形式 (-s, -es)
1282
+        if (lowerWord.endsWith('s') && lowerWord.length > 1) {
1283
+            // 基本复数形式 (books -> book)
1284
+            if (!lowerWord.endsWith('ss')) {
1285
+                possibleBaseWords.push(lowerWord.slice(0, -1));
1265 1286
             }
1266 1287
             
1267
-            // 处理以o结尾的名词复数形式
1268
-            if (lowerWord.endsWith('oes')) {
1269
-                possibleBaseWords.push(lowerWord.slice(0, -2)); // 如 heroes -> hero
1270
-                possibleBaseWords.push(lowerWord.slice(0, -1)); // 如 potatoes -> potato
1288
+            // 处理 -es 结尾 (boxes -> box)
1289
+            if (lowerWord.endsWith('es') && lowerWord.length > 2) {
1290
+                possibleBaseWords.push(lowerWord.slice(0, -2)); // 常规情况
1291
+                
1292
+                // 处理以ch, sh, ss, x, z结尾的名词复数形式 (boxes -> box)
1293
+                if (/(?:ch|sh|ss|x|z)es$/.test(lowerWord)) {
1294
+                    possibleBaseWords.push(lowerWord.slice(0, -2)); // 如 boxes -> box
1295
+                }
1296
+                
1297
+                // 处理以辅音+o结尾的名词复数形式 (heroes -> hero)
1298
+                if (lowerWord.endsWith('oes') && lowerWord.length > 3) {
1299
+                    possibleBaseWords.push(lowerWord.slice(0, -2)); // 如 heroes -> hero
1300
+                }
1301
+                
1302
+                // 处理以y结尾变为ies的情况 (cities -> city)
1303
+                if (lowerWord.endsWith('ies') && lowerWord.length > 3) {
1304
+                    const beforeY = lowerWord.slice(0, -3);
1305
+                    if (beforeY.length > 0 && /[a-z]$/.test(beforeY)) {
1306
+                        possibleBaseWords.push(beforeY + 'y');
1307
+                    }
1308
+                }
1271 1309
             }
1272 1310
         }
1273 1311
         
1274
-        // 处理以y结尾变为ies的情况
1275
-        if (lowerWord.endsWith('ies')) {
1276
-            possibleBaseWords.push(lowerWord.slice(0, -3) + 'y'); // 如 cities -> city
1277
-        }
1278
-        
1279
-        // 处理以fe结尾变为ves的情况
1280
-        if (lowerWord.endsWith('ves')) {
1312
+        // 处理以fe结尾变为ves的情况 (knives -> knife)
1313
+        if (lowerWord.endsWith('ves') && lowerWord.length > 4) {
1281 1314
             possibleBaseWords.push(lowerWord.slice(0, -3) + 'fe'); // 如 knives -> knife
1282
-            possibleBaseWords.push(lowerWord.slice(0, -3) + 'f'); // 如 leaves -> leaf
1315
+            possibleBaseWords.push(lowerWord.slice(0, -3) + 'f');  // 如 wives -> wife
1283 1316
         }
1284 1317
         
1285 1318
         // 处理特殊的复数形式
1286
-        if (lowerWord.endsWith('men')) {
1319
+        if (lowerWord.endsWith('men') && lowerWord.length > 3) {
1287 1320
             possibleBaseWords.push(lowerWord.slice(0, -3) + 'man'); // 如 women -> woman, men -> man
1288 1321
         }
1289
-        if (lowerWord.endsWith('ice')) {
1322
+        if (lowerWord.endsWith('ice') && lowerWord.length > 3) {
1290 1323
             possibleBaseWords.push(lowerWord.slice(0, -3) + 'ouse'); // 如 mice -> mouse
1291 1324
         }
1292
-        if (lowerWord.endsWith('eet')) {
1325
+        if (lowerWord.endsWith('eet') && lowerWord.length > 3) {
1293 1326
             possibleBaseWords.push(lowerWord.slice(0, -3) + 'oot'); // 如 feet -> foot
1294 1327
         }
1295
-        if (lowerWord.endsWith('ildren')) {
1328
+        if (lowerWord.endsWith('ildren') && lowerWord.length > 6) {
1296 1329
             possibleBaseWords.push(lowerWord.slice(0, -6) + 'ild'); // 如 children -> child
1297 1330
         }
1298 1331
         
1299 1332
         // 去重并过滤掉过短的单词
1300
-        const uniqueBaseWords = [...new Set(possibleBaseWords)].filter(w => w.length >= 2);
1301
-        
1302
-        // 如果没有找到任何可能的原形,或者所有可能的原形都不是有效单词,则返回单词本身
1303
-        if (uniqueBaseWords.length === 0 || !uniqueBaseWords.some(w => w === lowerWord || w.length >= 3)) {
1304
-            // 清空可能不正确的原形
1305
-            uniqueBaseWords.length = 0;
1306
-            uniqueBaseWords.push(lowerWord);
1307
-        }
1333
+        const uniqueBaseWords = [...new Set(possibleBaseWords)].filter(w => w.length >= 1);
1308 1334
         
1309 1335
         // 添加所有可能的原形到变形集合中
1310 1336
         uniqueBaseWords.forEach(base => allForms.add(base));
@@ -1313,14 +1339,14 @@ export const stringUtils = {
1313 1339
         const adjectiveSuffixes = ['ful', 'ous', 'ive', 'ic', 'al', 'ent', 'ant', 'able', 'ible', 'ary', 'ory', 'ish'];
1314 1340
         const verbSuffixes = ['ize', 'ise', 'ate', 'ify', 'en'];
1315 1341
         const nounSuffixes = ['tion', 'sion', 'ment', 'ness', 'ity', 'hood', 'ship', 'dom', 'ism', 'ist'];
1316
-        const adverbSuffixes = ['ly', 'ward', 'wise'];// 副词后缀
1342
+        const adverbSuffixes = ['ly', 'ward', 'wise']; // 副词后缀
1317 1343
 
1318 1344
         
1319 1345
         // 一些常见的形容词
1320 1346
         const commonAdjectives = ['good', 'bad', 'big', 'small', 'high', 'low', 'long', 'short', 'old', 'new', 
1321 1347
                                  'fast', 'slow', 'hard', 'soft', 'hot', 'cold', 'warm', 'cool', 'rich', 'poor', 
1322 1348
                                  'thick', 'thin', 'wide', 'narrow', 'deep', 'shallow', 'strong', 'weak', 'young', 
1323
-                                 'old', 'bright', 'dark', 'light', 'heavy', 'easy', 'hard', 'clean', 'dirty', 
1349
+                                 'bright', 'dark', 'light', 'heavy', 'easy', 'clean', 'dirty', 
1324 1350
                                  'full', 'empty', 'dry', 'wet', 'sick', 'healthy', 'loud', 'quiet', 'sweet', 
1325 1351
                                  'sour', 'bitter', 'nice', 'mean', 'kind', 'cruel', 'brave', 'afraid', 'happy', 
1326 1352
                                  'sad', 'angry', 'calm', 'busy', 'free', 'cheap', 'expensive', 'safe', 'dangerous'];
@@ -1349,50 +1375,58 @@ export const stringUtils = {
1349 1375
                 
1350 1376
         // 动词变形 (如果可能是动词)
1351 1377
         if (isLikelyVerb && lowerWord.length >= 2) {
1352
-            // 第三人称单数
1353
-            if (lowerWord.endsWith('s') || lowerWord.endsWith('x') || lowerWord.endsWith('ch') || lowerWord.endsWith('sh') || lowerWord.endsWith('z')) {
1354
-                allForms.add(lowerWord + 'es');
1355
-            } else if (lowerWord.endsWith('y') && !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2))) {
1356
-                allForms.add(lowerWord.slice(0, -1) + 'ies');
1357
-            } else {
1358
-                allForms.add(lowerWord + 's');
1378
+            // 第三人称单数 (walk -> walks)
1379
+            if (!lowerWord.endsWith('s')) {
1380
+                if (lowerWord.endsWith('s') || lowerWord.endsWith('x') || lowerWord.endsWith('ch') || lowerWord.endsWith('sh') || lowerWord.endsWith('z')) {
1381
+                    allForms.add(lowerWord + 'es');
1382
+                } else if (lowerWord.endsWith('y') && !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2))) {
1383
+                    allForms.add(lowerWord.slice(0, -1) + 'ies');
1384
+                } else {
1385
+                    allForms.add(lowerWord + 's');
1386
+                }
1359 1387
             }
1360 1388
             
1361 1389
             // 过去式和过去分词 (-ed)
1362
-            if (lowerWord.endsWith('e')) {
1363
-                allForms.add(lowerWord + 'd');
1364
-            } else if (lowerWord.endsWith('y') && !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2))) {
1365
-                allForms.add(lowerWord.slice(0, -1) + 'ied');
1366
-            } else if (lowerWord.length > 2 && 
1367
-                      !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 1)) && 
1368
-                      ['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2)) && 
1369
-                      !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 3))) {
1370
-                // 双写末尾辅音字母的情况,如 stop -> stopped
1371
-                allForms.add(lowerWord + lowerWord.charAt(lowerWord.length - 1) + 'ed');
1372
-            } else {
1373
-                allForms.add(lowerWord + 'ed');
1390
+            // 不对已经以-ed结尾的词添加-ed
1391
+            if (!lowerWord.endsWith('ed')) {
1392
+                if (lowerWord.endsWith('e')) {
1393
+                    allForms.add(lowerWord + 'd');
1394
+                } else if (lowerWord.endsWith('y') && !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2))) {
1395
+                    allForms.add(lowerWord.slice(0, -1) + 'ied');
1396
+                } else if (lowerWord.length > 2 && 
1397
+                          !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 1)) && 
1398
+                          ['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2)) && 
1399
+                          !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 3))) {
1400
+                    // 双写末尾辅音字母的情况,如 stop -> stopped
1401
+                    allForms.add(lowerWord + lowerWord.charAt(lowerWord.length - 1) + 'ed');
1402
+                } else {
1403
+                    allForms.add(lowerWord + 'ed');
1404
+                }
1374 1405
             }
1375 1406
             
1376 1407
             // 现在分词 (-ing)
1377
-            if (lowerWord.endsWith('ie')) {
1378
-                allForms.add(lowerWord.slice(0, -2) + 'ying');
1379
-            } else if (lowerWord.endsWith('e') && lowerWord.length > 2) {
1380
-                allForms.add(lowerWord.slice(0, -1) + 'ing');
1381
-            } else if (lowerWord.length > 2 && 
1382
-                      !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 1)) && 
1383
-                      ['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2)) && 
1384
-                      !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 3))) {
1385
-                // 双写末尾辅音字母的情况,如 run -> running
1386
-                allForms.add(lowerWord + lowerWord.charAt(lowerWord.length - 1) + 'ing');
1387
-            } else {
1388
-                allForms.add(lowerWord + 'ing');
1408
+            // 不对已经以-ing结尾的词添加-ing
1409
+            if (!lowerWord.endsWith('ing')) {
1410
+                if (lowerWord.endsWith('ie')) {
1411
+                    allForms.add(lowerWord.slice(0, -2) + 'ying');
1412
+                } else if (lowerWord.endsWith('e') && lowerWord.length > 2) {
1413
+                    allForms.add(lowerWord.slice(0, -1) + 'ing');
1414
+                } else if (lowerWord.length > 2 && 
1415
+                          !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 1)) && 
1416
+                          ['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2)) && 
1417
+                          !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 3))) {
1418
+                    // 双写末尾辅音字母的情况,如 run -> running
1419
+                    allForms.add(lowerWord + lowerWord.charAt(lowerWord.length - 1) + 'ing');
1420
+                } else {
1421
+                    allForms.add(lowerWord + 'ing');
1422
+                }
1389 1423
             }
1390 1424
         }
1391 1425
         
1392 1426
         // 形容词和副词变形 (如果可能是形容词或副词)
1393
-        if ((isLikelyAdjective || isLikelyAdverb) && lowerWord.length >= 3 && 
1427
+        if ((isLikelyAdjective || isLikelyAdverb) && lowerWord.length >= 2 && 
1394 1428
             !lowerWord.endsWith('ing') && !lowerWord.endsWith('ed') && 
1395
-            lowerWord.length <= 8) { // 限制长度,避免生成不必要的变形
1429
+            lowerWord.length <= 12) { // 限制长度,避免生成不必要的变形
1396 1430
             
1397 1431
             // 检查是否是多音节形容词,这些通常使用 more/most 而不是 -er/-est
1398 1432
             const isMultisyllabic = lowerWord.length > 7 || 
@@ -1409,33 +1443,37 @@ export const stringUtils = {
1409 1443
             // 只为短形容词生成比较级和最高级
1410 1444
             if (!isMultisyllabic) {
1411 1445
                 // 比较级 (-er)
1412
-                if (lowerWord.endsWith('e')) {
1413
-                    allForms.add(lowerWord + 'r');
1414
-                } else if (lowerWord.endsWith('y') && !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2))) {
1415
-                    allForms.add(lowerWord.slice(0, -1) + 'ier');
1416
-                } else if (lowerWord.length > 2 && 
1417
-                          !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 1)) && 
1418
-                          ['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2)) && 
1419
-                          !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 3))) {
1420
-                    // 双写末尾辅音字母的情况,如 big -> bigger
1421
-                    allForms.add(lowerWord + lowerWord.charAt(lowerWord.length - 1) + 'er');
1422
-                } else {
1423
-                    allForms.add(lowerWord + 'er');
1446
+                if (!lowerWord.endsWith('er')) {
1447
+                    if (lowerWord.endsWith('e')) {
1448
+                        allForms.add(lowerWord + 'r');
1449
+                    } else if (lowerWord.endsWith('y') && !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2))) {
1450
+                        allForms.add(lowerWord.slice(0, -1) + 'ier');
1451
+                    } else if (lowerWord.length > 2 && 
1452
+                              !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 1)) && 
1453
+                              ['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2)) && 
1454
+                              !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 3))) {
1455
+                        // 双写末尾辅音字母的情况,如 big -> bigger
1456
+                        allForms.add(lowerWord + lowerWord.charAt(lowerWord.length - 1) + 'er');
1457
+                    } else {
1458
+                        allForms.add(lowerWord + 'er');
1459
+                    }
1424 1460
                 }
1425 1461
                 
1426 1462
                 // 最高级 (-est)
1427
-                if (lowerWord.endsWith('e')) {
1428
-                    allForms.add(lowerWord + 'st');
1429
-                } else if (lowerWord.endsWith('y') && !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2))) {
1430
-                    allForms.add(lowerWord.slice(0, -1) + 'iest');
1431
-                } else if (lowerWord.length > 2 && 
1432
-                          !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 1)) && 
1433
-                          ['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2)) && 
1434
-                          !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 3))) {
1435
-                    // 双写末尾辅音字母的情况,如 big -> biggest
1436
-                    allForms.add(lowerWord + lowerWord.charAt(lowerWord.length - 1) + 'est');
1437
-                } else {
1438
-                    allForms.add(lowerWord + 'est');
1463
+                if (!lowerWord.endsWith('est')) {
1464
+                    if (lowerWord.endsWith('e')) {
1465
+                        allForms.add(lowerWord + 'st');
1466
+                    } else if (lowerWord.endsWith('y') && !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2))) {
1467
+                        allForms.add(lowerWord.slice(0, -1) + 'iest');
1468
+                    } else if (lowerWord.length > 2 && 
1469
+                              !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 1)) && 
1470
+                              ['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2)) && 
1471
+                              !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 3))) {
1472
+                        // 双写末尾辅音字母的情况,如 big -> biggest
1473
+                        allForms.add(lowerWord + lowerWord.charAt(lowerWord.length - 1) + 'est');
1474
+                    } else {
1475
+                        allForms.add(lowerWord + 'est');
1476
+                    }
1439 1477
                 }
1440 1478
             }
1441 1479
             
@@ -1443,8 +1481,8 @@ export const stringUtils = {
1443 1481
             if (!lowerWord.endsWith('ly')) {
1444 1482
                 if (lowerWord.endsWith('y') && !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2))) {
1445 1483
                     allForms.add(lowerWord.slice(0, -1) + 'ily');
1446
-                } else if (lowerWord.endsWith('le')) {
1447
-                    allForms.add(lowerWord.slice(0, -1) + 'y');
1484
+                } else if (lowerWord.endsWith('le') && lowerWord.length > 2) {
1485
+                    allForms.add(lowerWord.slice(0, -2) + 'ly');
1448 1486
                 } else {
1449 1487
                     allForms.add(lowerWord + 'ly');
1450 1488
                 }
@@ -1452,17 +1490,19 @@ export const stringUtils = {
1452 1490
         }
1453 1491
         
1454 1492
         // 名词复数形式 (对大多数单词都适用)
1455
-        if (lowerWord.length >= 2 && !lowerWord.endsWith('ing') && !lowerWord.endsWith('ed')) {
1456
-            if (lowerWord.endsWith('s') || lowerWord.endsWith('x') || lowerWord.endsWith('ch') || lowerWord.endsWith('sh') || lowerWord.endsWith('z')) {
1457
-                allForms.add(lowerWord + 'es');
1458
-            } else if (lowerWord.endsWith('y') && !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2))) {
1459
-                allForms.add(lowerWord.slice(0, -1) + 'ies');
1460
-            } else if (lowerWord.endsWith('f')) {
1461
-                allForms.add(lowerWord.slice(0, -1) + 'ves');
1462
-            } else if (lowerWord.endsWith('fe')) {
1463
-                allForms.add(lowerWord.slice(0, -2) + 'ves');
1464
-            } else {
1465
-                allForms.add(lowerWord + 's');
1493
+        if (lowerWord.length >= 2 && !lowerWord.endsWith('ing') && !lowerWord.endsWith('ed') && !lowerWord.endsWith('er') && !lowerWord.endsWith('est')) {
1494
+            if (!lowerWord.endsWith('s') && !lowerWord.endsWith('sh') && !lowerWord.endsWith('ch') && !lowerWord.endsWith('x') && !lowerWord.endsWith('z')) {
1495
+                if (lowerWord.endsWith('s') || lowerWord.endsWith('x') || lowerWord.endsWith('ch') || lowerWord.endsWith('sh') || lowerWord.endsWith('z')) {
1496
+                    allForms.add(lowerWord + 'es');
1497
+                } else if (lowerWord.endsWith('y') && !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2))) {
1498
+                    allForms.add(lowerWord.slice(0, -1) + 'ies');
1499
+                } else if (lowerWord.endsWith('f')) {
1500
+                    allForms.add(lowerWord.slice(0, -1) + 'ves');
1501
+                } else if (lowerWord.endsWith('fe')) {
1502
+                    allForms.add(lowerWord.slice(0, -2) + 'ves');
1503
+                } else {
1504
+                    allForms.add(lowerWord + 's');
1505
+                }
1466 1506
             }
1467 1507
         }
1468 1508
         
@@ -1490,4 +1530,4 @@ export const stringUtils = {
1490 1530
         
1491 1531
         return false;
1492 1532
     }
1493
-}
1533
+}