JavaScript怎样实现快速映射

javascript实现快速映射,类似这样:

let config = {
    '年|year|nian': 'year',
    '月|month|yue': 'month'
}

function a(type) {
    type = config[type]; // 只要type能和映射表某一键值匹配,则能快速映射为另一个值
    console.log(type);
}

a('年');
a('month');
a('year');

这样不用写if else,并且后续维护也比较简单,只要添加或者删除映射表里的映射规则即可

下面是我实现的映射方法,但是这样写效率太低了,每次都要遍历,而且都要new一个正则对象

let config = {
    '年|year|nian': 'year',
    '月|month|yue': 'month'
};
function getType(type) {
    let tstr,
    treg;
    type = type + '';
    for (tstr in config) {
        treg = new RegExp(tstr, 'g');
        if (treg.test(type)) {
            return config[tstr];
        }
    }
}
阅读 9.3k
5 个回答

思路

@angularbaby 要求添加说明。

首先很容易想到的是一个查找表(映射表),而 JS 里最简单的映射表就是 JS 对象。

从题主提供的 config 来看,是多个键对应同一个映射目标,多组这样的对应关系。而需要的结果是一对一的对应关系,所以很容易想到,将多对一关系拆分成多个一对一关系。

所以下面的代码就干了两件事情,① 将原来的一个 Key 拆分成多个 Key,生成一对一关系的映射表;② 提供一个查询函数,在生成的映射表中查询结果。

代码及演示

const a = (config => {
    const map = Object.keys(config)
        // 对原有 config 的 Key(list) 进行逐个聚合处理
        // 初始值是一个空映射表(空对象)
        // 每次聚合过程会添加若干键值对,键不同,值相同
        .reduce((dict, keys) => {
            // 缓存目标值,即标准的 year、month 等
            const target = config[keys];
            // 拆分 key(list),逐个将每个 key 添加到映射表中
            keys.split("|").forEach(key => dict[key] = target);
            return dict;
        }, {});

    // 反回一个查询函数,它只是简单的返回映射表中的查询值
    return function(key) {
        return map[key];
    };
})({
    "年|year|nian": "year",
    "月|month|yue": "month"
});

clipboard.png

可改进之处

现在这个处理没有考虑 config 更新的情况,但这个不是主要问题。主要问题是没有容错,如果调用 a() 的时候,没有找到相应的 key,会返回 undefined,这个可以按实际需求对返回值进行处理,比如

假设未查询,要求返回原值,那么可以将查询函数修改为

return map[key] || key;

我倒觉得你的映射表可以考虑这样:

const i18nMaps = {
    '年': 'year',
    'year': 'year',
    'nian': 'year',
    '月': 'month',
    'month': 'month',
    'yue': 'month'
};

console.log(i18nMaps['年'], i18nMaps['month'], i18nMaps['year']);

视乎更合理。

let config = {
    '年|year|nian': 'year',
    '月|month|yue': 'month'
};


> 考虑兼容情况

function getType(map) {
    let MAP = {};
    return function(type) {
        return MAP[type] != null ? MAP[type] : (function() {
            for (let names in map) {
                let namesArray = names.split('|');
                for (let i = 0, length = namesArray.length; i < length; i++) {
                    MAP[namesArray[i]] = map[names];
                }
            }
            return MAP[type] != null ? MAP[type] : '';
        })();
    }
}


> 不用考虑兼容情况

function get(map) {
    let MAP = {};
    return function(type) {
        return MAP && MAP[type] != null ? MAP[type] : (() = >{
            Object.keys(map).forEach((a) = >{ (a + '').split('|').forEach((b) = >{
                    MAP[b] = map[a];
                });
            });
            return MAP[type] != null ? MAP[type] : '';
        })();
    }
}

定义多个config:

let config1 = {
    '年|year|nian': 'year',
    '月|month|yue': 'month'
};
let config2 = {
    'a|b|c': 'name',
    'd|e|f': 'age'
};
let get1 = get(config1);
let get2 = get(config2);

上面的 get1、get2可以多次使用,像这样:

console.log(get1('年')); // year
console.log(get1('月')); // month
console.log(get2('a')); // name
console.log(get2('d')); // age

并且,因为第一次 get(xx) 的时候已经初始化了,所以后面使用 get1('xx') 进行查询的时候速度会显著提升

function a(type) {
    const keys = Object.keys(config)
    const find = keys.find(key => key.includes(type))
    if (!find) {
        console.error('type not find in cofig')
        return
    }
    // 对应的类型为 config[find]
    console.log(type, '对应的type: ', config[find])
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题