updated js优化

This commit is contained in:
mumuy
2025-04-12 12:35:28 +08:00
parent 5de00bca62
commit a706d387cc
11 changed files with 166 additions and 203 deletions
+12 -11
View File
@@ -5,22 +5,23 @@ import _input from './data/input.js';
import _sort from './data/sort.js';
import {modeData} from './mode.js';
let _hash = Object.assign({},modeData);
for(let key in _input){
_hash[key] = (_hash[key]||[]).concat(_input[key]);
}
for(let key in _sort){
_hash[key] = (_hash[key]||[]).concat(_sort[key]);
function mergeValues(target, source) {
Object.entries(source).forEach(([key, value]) => {
target[key] = (target[key] || []).concat(value);
});
return target;
}
let _hash = mergeValues({...modeData }, _input);
_hash = mergeValues(_hash, _sort);
let cacheData = {};
for(let key in _hash){
_hash[key].forEach(function(name){
if(typeof cacheData[name]=='undefined'){
Object.entries(_hash).forEach(([key, names]) => {
names.forEach((name) => {
if (!cacheData[name]) {
cacheData[name] = [];
}
cacheData[name].push(key);
});
}
});
export {cacheData};
export {cacheData};
+40 -46
View File
@@ -44,12 +44,11 @@ export function reverseId(id,sex){
sex = 0;
}
}
let doing = function(sex){
let sid = (','+sex+','+id).replace(/,[fhs]|,[olx]b/g,',1').replace(/,[mwd]|,[olx]s/g,',0');
sid = sid.substring(0,sid.length-2);
let sid_arr = sid.split(',').reverse();
let r_id = id.split(',').reverse().map((id,i)=>hash[id][sid_arr[i]]).join(',');
let gen = getGenById(r_id);
const doing = function(sex){
const sid = (','+sex+','+id).replace(/,[fhs]|,[olx]b/g,',1').replace(/,[mwd]|,[olx]s/g,',0');
const sid_arr = sid.substring(0,sid.length-2).split(',').reverse();
const r_id = id.split(',').reverse().map((id,i)=>hash[id][sid_arr[i]]).join(',');
const gen = getGenById(r_id);
return r_id + (gen?'':age);
};
if(sex<0){
@@ -61,19 +60,19 @@ export function reverseId(id,sex){
// ID列表去重
export function filterId(arr){
let sameList = arr.filter(item=>item==item.replace(/[ol](?=[s|b])/g,'x').replace(/&[ol]/,''));
return arr.filter(item=>{
let temp = item.replace(/[ol](?=[s|b])/g,'x').replace(/&[ol]/,'');
const sameList = arr.filter(item => item === item.replace(/[ol](?=[s|b])/g,'x').replace(/&[ol]/,''));
return arr.filter(item => {
const temp = item.replace(/[ol](?=[s|b])/g,'x').replace(/&[ol]/,'');
return sameList.includes(item)||item!=temp&&!sameList.includes(temp);
}).filter((item,idx,arr) => arr.indexOf(item) === idx);
};
// 通过ID获取世代数
export function getGenById(id){
let gMap = {'f':1,'m':1,'s':-1,'d':-1};
const gMap = {'f':1,'m':1,'s':-1,'d':-1};
let gen = 0;
id.split(',').forEach(function(sub){
let s = sub.replace(/&[ol\d]+/,'');
id.split(',').forEach(sub => {
const s = sub.replace(/&[ol\d]+/,'');
gen += gMap[s]||0;
});
return gen;
@@ -82,29 +81,26 @@ export function getGenById(id){
// 通过ID获取关系称呼
export function getItemsById(id){
let items = [];
let getData = function(key){
const getData = function(key){
let ids = [];
let k1 = key.replace(/(,[sd])(,[wh])?$/,'$1&o$2');
let k2 = key.replace(/(,[sd])(,[wh])?$/,'$1&l$2');
const k1 = key.replace(/(,[sd])(,[wh])?$/,'$1&o$2');
const k2 = key.replace(/(,[sd])(,[wh])?$/,'$1&l$2');
if(modeData[k1]&&modeData[k2]){
ids = [k1,k2];
}else if(modeData[key]){
ids = [key];
}
return filterId(ids).map(function(id){
return modeData[id][0];
});
return filterId(ids).map(id => modeData[id][0]);
};
// 对排序进行处理
if(id.match(/&([\d]+)(,[hw])?$/)){
let num = id.match(/&([\d]+)(,[hw])?$/)[1];
let zh = number2zh(num);
const num = id.match(/&([\d]+)(,[hw])?$/)[1];
const zh = number2zh(num);
id = id.replace(/&\d+/g,'');
if(_sort[id]){
let item = _sort[id][0].replace('几',zh);
items.push(item);
items.push(_sort[id][0].replace('几',zh));
}else if(modeData[id]){
let gen = getGenById(id);
const gen = getGenById(id);
let item = '';
if(gen<3&&!id.match(/[hw],/)){
modeData[id].forEach(function(name){
@@ -145,13 +141,14 @@ export function getItemsById(id){
};
// 通过ID获取关系链
let data = Object.assign({},modeData,{
'xb':['兄弟'],
'xs':['姐妹']
});
let data = {
...modeData,
'xb': ['兄弟'],
'xs': ['姐妹']
};
export function getChainById(id,sex=-1){
let item = id.split(',').map(function(sign){
let key = sign.replace(/&[ol\d]+/,'');
let item = id.split(',').map(sign => {
const key = sign.replace(/&[ol\d]+/,'');
return data[key][0];
}).join('的');
if(sex>-1&&data[sex+','+id]){
@@ -166,26 +163,23 @@ export function getChainById(id,sex=-1){
// 通过ID获取关系合称
export function getPairsById(id1,id2){
id1 = id1.replace(/&\d+/g,'');
id2 = id2.replace(/&\d+/g,'');
const id1_x = id1.replace(/([ol])([bs])/g,'x$2');
const id2_x = id2.replace(/([ol])([bs])/g,'x$2');
const id1_r = id1.replace(/&[ol]/g,'');
const id2_r = id2.replace(/&[ol]/g,'');
let result = [];
let result_x = [];
let result_r = [];
id1 = id1.replace(/&\d+/g,'');
id2 = id2.replace(/&\d+/g,'');
let id1_x = id1.replace(/([ol])([bs])/g,'x$2');
let id2_x = id2.replace(/([ol])([bs])/g,'x$2');
let id1_r = id1.replace(/&[ol]/g,'');
let id2_r = id2.replace(/&[ol]/g,'');
for(let key in _pair){
let selectors = key.split('#');
for(const key in _pair){
const selectors = key.split('#');
if(selectors.length>1){
let list1 = selector2id(selectors[0]);
let list2 = selector2id(selectors[1]);
let list1_r = list1.map(function(selector){
return selector.replace(/&[ol\d]+/,'').replace(/([ol])([bs])/,'x$2');
});
let list2_r = list2.map(function(selector){
return selector.replace(/&[ol\d]+/,'').replace(/([ol])([bs])/,'x$2');
});
const list1 = selector2id(selectors[0]);
const list2 = selector2id(selectors[1]);
const list1_r = list1.map(selector => selector.replace(/&[ol\d]+/,'').replace(/([ol])([bs])/,'x$2'));
const list2_r = list2.map(selector => selector.replace(/&[ol\d]+/,'').replace(/([ol])([bs])/,'x$2'));
if(list1.includes(id1)&&list2.includes(id2)||list1.includes(id2)&&list2.includes(id1)){
result.push(_pair[key][0]);
}
@@ -204,4 +198,4 @@ export function getPairsById(id1,id2){
result = result_r;
}
return result;
};
};
+26 -33
View File
@@ -8,46 +8,39 @@ import _multipie from './data/multiple.js';
import {expandSelector} from './selector.js';
let _map = Object.assign({},_multipie);
let _map = { ..._multipie };
// 分支 - 前缀处理
let prefixMap = {};
for(let key in _prefix){
const prefixMap = {};
for(const key in _prefix){
prefixMap[key] = {};
for(let selector in _prefix[key]){
for(const selector in _prefix[key]){
expandSelector(selector).forEach(function(s){
prefixMap[key][s] = _prefix[key][selector];
});
}
}
// 分支 - 节点处理
let branchMap = {};
for(let selector in _branch){
const branchMap = {};
for(const selector in _branch){
expandSelector(selector).forEach(function(s){
branchMap[s] = _branch[selector];
});
}
// 分支 - 合并
let getMap = function(prefixMap,branchMap){
let map = {};
for(let key in branchMap){
let tag = key.match(/\{.+?\}/)[0];
let nameList = branchMap[key];
for(let k in prefixMap[tag]){
let prefixList = prefixMap[tag][k];
let newKey = key.replace(tag,k);
let isFilter = ['h,h','w,w','w,h','h,w'].some(pair=>(newKey.includes(pair)));
const getMap = function(prefixMap,branchMap){
const map = {};
for(const key in branchMap){
const tag = key.match(/\{.+?\}/)[0];
const nameList = branchMap[key];
for(const k in prefixMap[tag]){
const prefixList = prefixMap[tag][k];
const newKey = key.replace(tag,k);
const isFilter = ['h,h','w,w','w,h','h,w'].some(pair=>(newKey.includes(pair)));
if(!isFilter){
let newList = [];
prefixList.forEach(function(prefix){
nameList.forEach(function(name){
if(name.includes('?')){
newList.push(name.replace('?',prefix));
}else{
newList.push(prefix+name);
}
});
});
const newList = prefixList.flatMap((prefix) =>
nameList.map((name) => (name.includes('?') ? name.replace('?', prefix) : prefix + name))
);
if(!map[newKey]){
map[newKey] = _map[newKey]||[];
}
@@ -57,11 +50,11 @@ let getMap = function(prefixMap,branchMap){
}
return map;
};
_map = Object.assign({},_map,getMap(prefixMap,branchMap));
_map = {..._map,...getMap(prefixMap,branchMap)};
// 主要关系
for(let key in _main){
_map[key] = [].concat(_main[key],_map[key]||[]);
_map[key] = [..._main[key], ...(_map[key] || [])];
}
// 版权彩蛋
@@ -72,10 +65,10 @@ const mateMap = {
'w':['妻','内','岳','岳家','丈人'],
'h':['夫','外','公','婆家','婆婆'],
};
let nameSet = new Set(Object.values(_map).flat());
for(let key in _map){
const nameSet = new Set(Object.values(_map).flat());
for(const key in _map){
if(key.match(/^[fm]/)||key.match(/^[olx][bs]$|^[olx][bs],[^mf]/)){ // 只对长辈或者兄弟辈匹配
for(let k in mateMap){
for(const k in mateMap){
let newKey = k+','+key;
if(key.match(/[fm]/)){
let newKey_x = newKey.replace(/,[ol]([sb])(,[wh])?$/,',x$1$2').replace(/(,[sd])&[ol](,[wh])?$/,'$1$2');
@@ -86,11 +79,11 @@ for(let key in _map){
if(!_map[newKey]){
_map[newKey] = [];
}
let prefixList = mateMap[k];
let nameList = _map[key];
const prefixList = mateMap[k];
const nameList = _map[key];
prefixList.forEach(function(prefix){
nameList.forEach(function(name){
let newName = prefix+name;
const newName = prefix+name;
if(!nameSet.has(newName)){ // 配偶组合的称呼不得与原有称呼冲突(如:妻舅!=妻子的舅舅;外舅公!=老公的舅公)
_map[newKey].push(newName);
}
+5 -5
View File
@@ -4,22 +4,22 @@
import _map from './map.js';
let _mode = {}; // 模式缓存
let modeData = Object.assign({},_map); // 最终数据
let modeData = { ..._map }; // 最终数据
// 设置模式数据
export function setModeData(sign,data){
_mode[sign] = Object.assign(_mode[sign]||{},data);
_mode[sign] = { ...(_mode[sign] || {}), ...data };
};
// 获取模式数据
export function getModeData(sign){
modeData = Object.assign({},_map);
modeData = { ..._map };
if(sign&&_mode[sign]){
for(let key in _mode[sign]){
for(const key in _mode[sign]){
modeData[key] = [].concat(_mode[sign][key],_map[key]||[]);
}
}
return modeData;
};
export {modeData};
export {modeData};
+2 -2
View File
@@ -4,8 +4,8 @@
import _expression from './rule/expression.js';
export function getOptions(text){
for(let item of _expression){
let match = text.match(item['exp']);
for(const item of _expression){
const match = text.match(item['exp']);
if(match){
return item['opt'](match);
}
+37 -49
View File
@@ -10,7 +10,7 @@ import {reverseId,filterId,getGenById} from './id.js';
import {cacheData} from './cache.js';
// 获得最简
let getOptimal = function(options){
const getOptimal = function(options){
let {
from,
to,
@@ -81,18 +81,18 @@ export function getSelectors(str){
str = str.replace(/(伯|叔)+(父|母)?家的?(哥|姐|弟|妹)+/,'堂$3').replace(/(伯|叔)+(父|母)?家的?/,'堂');
str = str.replace(/姨+(爸|父|丈|妈|母)?家的?(哥|姐|弟|妹)+/,'姨$2').replace(/姨+(爸|父|丈|妈|母)?家的?/,'姨');
let lists = str.split('的');
const lists = str.split('的');
let result = [];
let isMatch = true;
while(lists.length){
let name = lists.shift(); //当前匹配词
const name = lists.shift(); //当前匹配词
let items = []; //当前匹配词可能性
let keywords = [name];
const keywords = [name];
let getList = function(name){
// 词义扩展
_replace.forEach(item => {
item['arr'].forEach(word =>{
let name1 = name.replace(item['exp'],word);
const name1 = name.replace(item['exp'],word);
if(name1!=name){
keywords.push(name1);
getList(name1);
@@ -100,9 +100,9 @@ export function getSelectors(str){
});
});
// 同义词替换
for(let word in _similar){
let name1 = name.replace(word,_similar[word]);
let name2 = name.replace(_similar[word],word);
for(const word in _similar){
const name1 = name.replace(word,_similar[word]);
const name2 = name.replace(_similar[word],word);
if(name1!=name){
keywords.push(name1);
}
@@ -113,19 +113,19 @@ export function getSelectors(str){
};
getList(name);
// 通过关键词找关系
let items_map = [[],[],[]];
const items_map = [[],[],[]];
keywords.forEach(function(name){
name = name.replace(/^[尕幺细满碎晚末尾幼]/,'小');
let match = name.match(/^[大|小]|^[一|二|三|四|五|六|七|八|九|十]+/);
const match = name.match(/^[大|小]|^[一|二|三|四|五|六|七|八|九|十]+/);
if(match){ // 匹配排序
let x_name = name.replace(match[0],'几');
let r_name = name.replace(match[0],'');
let num = zh2number(match[0]);
[x_name,r_name,name].forEach(function(name,index){
let ids = cacheData[name];
const x_name = name.replace(match[0],'几');
const r_name = name.replace(match[0],'');
const num = zh2number(match[0]);
[x_name,r_name,name].forEach((name, index) => {
const ids = cacheData[name];
if(ids&&ids.length){
ids.forEach(function(i){
let id = i.replace(/(,[hw])$/,'&'+num+'$1').replace(/([^hw]+)$/,'$1&'+num);
ids.forEach(i => {
const id = i.replace(/(,[hw])$/,'&'+num+'$1').replace(/([^hw]+)$/,'$1&'+num);
if(!i.match(/^[mf,]+$/)&&!name.match(/^[从世]/)){ // 直系祖辈不参与排序
items_map[index].push(id);
}
@@ -146,7 +146,7 @@ export function getSelectors(str){
if(!items.length){
isMatch = false;
}
let res = [];
const res = [];
if(!result.length){
result = [''];
}
@@ -168,25 +168,15 @@ export function mergeSelector(param){
sex:my_sex
} = param;
if(my_sex<0){
let to_sex = -1;
let from_sex = -1;
if(from_selector.match(/^,[w1]/)){
from_sex = 1;
}else if(from_selector.match(/^,[h0]/)){
from_sex = 0;
}
if(to_selector.match(/^,[w1]/)){
to_sex = 1;
}else if(to_selector.match(/^,[h0]/)){
to_sex = 0;
}
if(from_sex==-1&&to_sex>-1){
my_sex = to_sex;
}else if(from_sex>-1&&to_sex==-1){
my_sex = from_sex;
}else if(from_sex==to_sex){
my_sex = from_sex;
}else{
const fromSex = from_selector.match(/^,[w1]/) ? 1 : from_selector.match(/^,[h0]/) ? 0 : -1;
const toSex = to_selector.match(/^,[w1]/) ? 1 : to_selector.match(/^,[h0]/) ? 0 : -1;
if (fromSex === -1 && toSex > -1) {
my_sex = toSex;
} else if (fromSex > -1 && toSex === -1) {
my_sex = fromSex;
} else if (fromSex === toSex) {
my_sex = fromSex;
} else {
return [];
}
}
@@ -195,9 +185,9 @@ export function mergeSelector(param){
if(!from_ids.length||!to_ids.length){
return [];
}
let result = [];
from_ids.forEach(function(from){
to_ids.forEach(function(to){
const result = [];
from_ids.forEach(from => {
to_ids.forEach(to => {
let sex = my_sex;
let selector = ','+to;
if(selector.match(/,([fhs1](&[ol\d]+)?|[olx]b)(&[ol\d]+)?$/)){
@@ -239,15 +229,15 @@ export function mergeSelector(param){
// 扩展选择器
export function expandSelector(selector){
let result = [];
let hash = {};
let getSelector = function(selector){
let s='';
const result = [];
const hash = {};
const getSelector = function(selector){
if(!hash[selector]){
hash[selector] = true;
let s='';
do{
s = selector;
for(let item of _filter){
for(const item of _filter){
// console.log('[filter]',item['exp'],selector);
selector = selector.replace(item['exp'],item['str']);
if(selector.includes('#')){
@@ -289,8 +279,6 @@ export function selector2id(selector,sex){
if(selector.match(/,[mwd0](&[ol\d]+)?,w|,[hfs1](&[ol\d]+)?,h/)){ //同志关系去除
return [];
}
let result = expandSelector(selector).map(function(selector){
return selector.replace(/,[01]/,'').substr(1); //去前面逗号和性别信息
});
const result = expandSelector(selector).map(selector => selector.replace(/,[01]/, '').substr(1)); //去前面逗号和性别信息
return filterId(result);
};
};
+36 -49
View File
@@ -4,44 +4,39 @@ import {reverseId,getItemsById,getChainById,getPairsById} from './module/id.js';
import {setModeData,getModeData,modeData} from './module/mode.js';
// 对外方法
let relationship = function (parameter){
let relationship = function (parameter) {
if(typeof parameter =='string'){
parameter = getOptions(parameter);
}
let options = Object.assign({
text:'', // 目标对象:目标对象的称谓汉字表达,称谓间用‘的’字分隔
target:'', // 相对对象:相对对象的称谓汉字表达,称谓间用‘的’字分隔,空表示自己
sex:-1, // 本人性别:0表示女性,1表示男性
type:'default', // 转换类型:'default'计算称谓,'chain'计算关系链,'pair'计算关系合称
reverse:false, // 称呼方式:true对方称呼我,false我称呼对方
mode:'default', // 模式选择:使用setMode方法定制不同地区模式,在此选择自定义模式
optimal:false // 最短关系:计算两者之间的最短关系
},parameter);
text: '', // 目标对象:目标对象的称谓汉字表达,称谓间用‘的’字分隔
target: '', // 相对对象:相对对象的称谓汉字表达,称谓间用‘的’字分隔,空表示自己
sex: -1, // 本人性别:0表示女性,1表示男性
type: 'default', // 转换类型:'default'计算称谓,'chain'计算关系链,'pair'计算关系合称
reverse: false, // 称呼方式:true对方称呼我,false我称呼对方
mode: 'default', // 模式选择:使用setMode方法定制不同地区模式,在此选择自定义模式
optimal: false // 最短关系:计算两者之间的最短关系
}, parameter);
// 切换模式
getModeData(options.mode);
let from_selectors = getSelectors(options.text);
let to_selectors = getSelectors(options.target);
if(!to_selectors.length){
to_selectors = [''];
let fromSelectors = getSelectors(options.text);
let toSelectors = getSelectors(options.target);
if (!toSelectors.length) {
toSelectors = [''];
}
let result = []; //匹配结果
// console.log('[selectors]',from_selectors,to_selectors);
from_selectors.forEach(function(from_selector){
to_selectors.forEach(function(to_selector){
mergeSelector({
from:from_selector,
to:to_selector,
sex:options.sex,
optimal:options.optimal
}).forEach(function(data){
// console.log('[data]',from_selector,to_selector,options.optimal,data);
let ids = data?selector2id(data['selector'],data['sex']):[];
// console.log('[ids]',data['selector'],data['sex'],ids);
ids.forEach(function(id){
const result = fromSelectors.flatMap(fromSelector => {
return toSelectors.flatMap(toSelector => {
return mergeSelector({
from: fromSelector,
to: toSelector,
sex: options.sex,
optimal: options.optimal
}).flatMap(data => {
const ids = data ? selector2id(data['selector'], data['sex']) : [];
return ids.flatMap(id => {
let temps = [id];
let sex = data['sex'];
if(options.reverse){
if (options.reverse) {
temps = reverseId(id,sex);
if(id.match(/([fhs1](&[ol\d]+)?|[olx]b)$/)){
sex = 1;
@@ -49,33 +44,25 @@ let relationship = function (parameter){
sex = 0;
}
}
if(options.type=='chain'){
temps.forEach(function(id){
let item = getChainById(id,data['sex']);
if(item){
result.push(item);
}
});
}else if(options.type=='pair'){
temps = reverseId(id,data['sex']);
temps.forEach(function(r_id){
let pairs = getPairsById(id,r_id);
result = result.concat(pairs);
});
}else{
temps.forEach(function(id){
if (options.type === 'chain') {
return temps.map(id => getChainById(id, sex)).filter(item => item);
} else if (options.type === 'pair') {
const reversedTemps = reverseId(id, data['sex']);
return reversedTemps.flatMap(rId => getPairsById(id, rId));
} else {
return temps.flatMap(id => {
let items = getItemsById(id);
if(!items.length){
items = getItemsById(sex+','+id);
if (!items.length) {
items = getItemsById(sex + ',' + id);
}
result = result.concat(items);
return items;
});
}
});
});
});
});
// console.log('[result]',result);
return [...new Set(result)];
};
@@ -86,4 +73,4 @@ relationship.dataCount = Object.keys(modeData).length;
// 设置语言模式
relationship.setMode = setModeData;
export default relationship;
export default relationship;