Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 模板和占位符算法_Javascript_Algorithm_Templates_Placeholder - Fatal编程技术网

Javascript 模板和占位符算法

Javascript 模板和占位符算法,javascript,algorithm,templates,placeholder,Javascript,Algorithm,Templates,Placeholder,首先是一个快速定义:) 模板-可能包含占位符的字符串(例如:“hello[name]”) 占位符-方括号中的子字符串(例如“hello[name]:”中的“name”) 属性映射-以字符串作为值的有效对象 我需要编写一个代码,用属性映射中的匹配值替换占位符(以及括号) 例如: 对于以下属性映射: { "name":"world", "my":"beautiful", "a":"[b]", "b":"c", "c":"my" } 预期成果: “你好名

首先是一个快速定义:)

  • 模板-可能包含占位符的字符串(例如:“hello[name]”)
  • 占位符-方括号中的子字符串(例如“hello[name]:”中的“name”)
  • 属性映射-以字符串作为值的有效对象
我需要编写一个代码,用属性映射中的匹配值替换占位符(以及括号)

例如: 对于以下属性映射:

{
    "name":"world",
    "my":"beautiful",
    "a":"[b]",
    "b":"c",
    "c":"my"
}
预期成果:

  • “你好名字”->“你好名字”

  • “你好[姓名]”->“你好,世界”

  • “[b]”->“c”

  • “[a]”->“c”(因为[a]->[b]->[c])

  • “[[b]]”->“我的”(因为[[b]]->[c]->我的)

  • “你好[我的][名字]”->“你好,美丽的世界”


由@chris给出的答案非常好,我只想提供一个使用正则表达式的替代解决方案,它“反过来”工作,也就是说,不寻找“占位符版本”的出现属性映射中的所有项,但通过重复查找占位符本身的出现,并用属性映射中的相应值替换它。这有两个好处:

  • 如果属性映射变得非常大,则此解决方案应具有 更好的性能(仍有待于基准测试)
  • 通过调整正则表达式和替换函数,可以轻松修改占位符和替换工作方式(这里可能不是问题)
  • 当然,缺点是代码有点复杂(部分原因是JavaScript缺乏一种使用自定义函数替换正则表达式匹配的好方法,所以这就是
    substituteRegExp
    的作用):

    更新:我做了一些分析来比较这两种解决方案(JSFIDLE at,我还使用了Firebug)。虽然@chris解决方案对于小字符串更快(不需要解析正则表达式等),但该解决方案对于大字符串(以数千个字符的顺序)的性能要好得多。我并没有比较不同大小的房产地图,但我预计会有更大的差异


    理论上,此解决方案具有运行时O(kn),其中k是占位符嵌套的深度,n是字符串的长度(假设字典/哈希查找需要恒定的时间),而@chris的解决方案是O(knm),其中m是属性映射中的项数。当然,所有这些都只与大型输入相关。

    如果您熟悉.NET的
    String.Format
    ,那么您应该看看。它也支持数字格式,就像
    String.Format

    下面是一个如何使用它的示例:

    var result = String.Format("Hello {my} {name}", map);
    

    但是,执行递归模板需要一些修改。

    如果有循环,如a->[b]和b->[a],会发生什么?此外,是否所有决策都是强制的(即,没有键映射到多个值?)当然,忽略循环。将地图对象视为ValIdxCelt!这正是我所需要的!非常感谢谢谢你,这真是太详细了!
    function substituteRegExp(string, regexp, f) {
        // substitute all matches of regexp in string with the value
        // returned by f given a match and the corresponding group values
        var found;
        var lastIndex = 0;
        var result = "";
        while (found = regexp.exec(string)) {
            var subst = f.apply(this, found);
            result += string.slice(lastIndex, found.index) + subst;
            lastIndex = found.index + found[0].length;
        }
        result += string.slice(lastIndex);
        return result;
    }
    
    function templateReplace(string, values) {
        // repeatedly substitute [key] placeholders in string by values[key]
        var placeholder = /\[([a-zA-Z0-9]+)\]/g;
        while (true) {
            var newString = substituteRegExp(string, placeholder, function(match, key) {
                return values[key];
            });
            if (newString == string)
                break;
            string = newString;
        }
        return string;
    }
    
    alert(templateReplace("hello [[b]] [my] [name]", {
        "name":"world",
        "my":"beautiful",
        "a":"[b]",
        "b":"c",
        "c":"my"
    })); // -> "hello my beautiful world"
    
    var result = String.Format("Hello {my} {name}", map);