根据对象图

时间:2017-03-20 14:24:59

标签: javascript algorithm recursion

我有一个很大的URL路径列表,我需要转换它。如何转换每个URL的规则表示为对象。即对于输入

const inputUrls = [
    '(entrance)',
    '/Introduction',
    '/about',
    '/car-models',
    '/car-models/ct/',
    '/car-models/ct',
    '/car-models/ct/ct-200h',
    '/',
    '/',
    '/car-models/ls/',
    '/car-models/ls',
    '/car-models/ls/ls-200h',
    'car-config.example.com/',
];

加上这些规则

const rules = {
    'about': {},
    'car-models': { 'ct': { 'ct-200h': {} } },
    'car-config.example.com': {}
};

输出应为:

const outputUrls = [
    '(entrance)',
    '/Introduction',
    '/about',
    '/car-models',
    '/car-models/ct',
    '/car-models/ct',
    '/car-models/ct/ct-200h',
    '/',
    '/',
    '/car-models',
    '/car-models',
    '/car-models',
    'car-config.example.com',
];

如下所示:所有网址都应转换为最近的单一级目录

const rules = {};
transform('/car-models/ct/ct-200h', rules) === '/car-models'

除非规则对象包含该目录,在这种情况下它应该保留另一个目录级别,即

const rules = { 'car-models': {} };
transform('/car-models/ct/ct-200h', rules) === '/car-models/ct'

我尝试以几种不同的方式创建transform功能。这就是我现在所拥有的。我认为它沿着正确的路线行进,但它显然不适用于所有情况,尤其是根本不包含/的网址。

function transform(rules = {}, url = '', isInternal = true) {

    if (url === '' || url === '/') {
        return isInternal ? '' : url;
    } else {
        const splitUrl = url.split('/');
        const firstPart = splitUrl[0];
        const nextParts = splitUrl.slice(1);

        if (splitUrl.length < 2) {
            return firstPart;
        } else {
            const branch = rules[firstPart === '' ? splitUrl[1] : firstPart];
            if (branch) {
                const merged = nextParts.join('/');
                return transform(branch, merged);
            } else {
                return url;
            }
        }
    }
}

2 个答案:

答案 0 :(得分:1)

您可以迭代拆分的URL并执行规则。然后切片是否找到零件。

var inputUrls = ['(entrance)', '/Introduction', '/about', '/car-models', '/car-models/ct/', '/car-models/ct', '/car-models/ct/ct-200h', '/', '/', '/car-models/ls/', '/car-models/ls', '/car-models/ls/ls-200h', 'car-config.example.com/', 'car-config.example.com/stuff'],
    rules = { 'about': {}, 'car-models': { 'ct': { 'ct-200h': {} } }, 'car-config.example.com': {} },
    outputUrls = inputUrls.map(function (a) {
        var o = rules,
            p = a.split('/'),
            i = +!p[0],        // correction for first slash/empty string
            offset = 1;

        while (p[i] in o) {
            offset = 0;
            o = o[p[i]];
            i++;
        }
        return p.slice(0, i + offset).join('/');
    });

console.log(outputUrls);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 1 :(得分:1)

抱歉迟到了。我没有彻底检查我的解决方案,但结果适合你。

&#13;
&#13;
function transform(paths, rulesTree) {

  return paths.map((path) => {
  
    let lastRoot = rulesTree;
    const resultTokens = [];
    let ifOnlyBranch = false;
    const inputTokens = path.replace(/(?:^\/|\/$)/g, '').split('/');
    const ifAll = inputTokens.every((pathToken) => {

      resultTokens.push(pathToken);
      ifOnlyBranch = !Object.keys(lastRoot).length;
      lastRoot = lastRoot[pathToken];
      return lastRoot;
    
    });
    let res;
    if (ifAll || ifOnlyBranch) {
      res = resultTokens;
    } else {
      res = resultTokens.slice(0, Math.max(1, resultTokens.length - 1));
    }
    const prefix = path[0] === '/' ? '/' : '';
    return prefix + res.join('/');
  
  });

}

const inputUrls = [
    '(entrance)',
    '/Introduction',
    '/about',
    '/car-models',
    '/car-models/ct/',
    '/car-models/ct',
    '/car-models/ct/ct-200h',
    '/',
    '/',
    '/car-models/ls/',
    '/car-models/ls',
    '/car-models/ls/ls-200h',
    'car-config.example.com/',
];

const rules = {
    'about': {},
    'car-models': { 'ct': { 'ct-200h': {} } },
    'car-config.example.com': {}
};

console.log( transform(inputUrls, rules) );
&#13;
&#13;
&#13;