我正试图想出一种有效的方法来覆盖看起来像这样的2个字符串:
str1 = "width=800,height=600,resizable=no,titlebar=no";
str2 = "width=100,height=100";
在上面的示例中,str2
应覆盖str1
以生成str3
:
str3 = "width=100,height=100,resizable=no,titlebar=no";
在我的测试中,我将str2
转换为数组并针对str1
中的匹配对每个键进行了测试。
任何人都可以想到一种更有效的方法来写这个:
str1 = "width=800,height=600,resizable=no,titlebar=no";
str2 = "width=100,height=100";
sArray = str2.split(",");
for( var i = 0; i < sArray.length; i++ ) {
var key = sArray[i].match(/(\w+)=/gi).toString().replace("=", ""),
in_str1 = str1.search(key),
replace_pattern = new RegExp(key+"=(\\w+)", "gi");
if(in_str1 !== -1){
str1 = str1.replace(replace_pattern, sArray[i]);
} else {
str1 = str1 + "," + sArray[i];
}
}
答案 0 :(得分:7)
这是一个非常简洁的基于正则表达式的解决方案:
str3 = str2 + "," + str1;
while ((temp = str3.replace(/\b([a-z]+)(=.*)\b\1=[^,]*,?/, "$1$2")) != str3) {
str3 = temp;
}
它的工作原理是将覆盖的字符串添加到可覆盖的字符串中,然后重复地删除稍后在连接的字符串中出现的重复项,直到没有。
如果任何一个字符串可能为空,或者如果允许任何类型的转义,或者如果键只能用字母命名,则需要更加小心。
答案 1 :(得分:2)
没有尝试运行它,但这应该有效,创建了一个实用函数parseParamString
,它接受该格式的字符串,并且可选择一个对象来添加键值对。
function parseParamString(str, obj) {
var pairs = str.split(","),
i = 0, l = pairs.length,
pair;
obj || (obj = {});
for (; l > i; ++i) {
pair = pairs[i].split("=", 2);
obj[pair[0]] = pair[1];
}
return obj;
}
function buildParamString(obj) {
var pairs = [], i;
for (i in obj) {
if (obj.hasOwnProperty(i)) {
pairs.push(i + "=" + obj[i]);
}
}
return pairs.join(",");
}
var str1 = "width=800,height=600,resizable=no,titlebar=no",
str2 = "width=100,height=100";
var resultObj = parseParamString(str2, parseParamString(str1));
var resultSTr = buildParamString(resultObj);
修改:忘记将对象转回字符串。
答案 2 :(得分:2)
我想出了以下内容,但我不确定它是否会比你的方法更快,因为还有更多的步骤。还有点长......
var toObj = function (str) {
var arr = str.split(","), obj = {};
for (var i = 0; i < arr.length; i++) {
var keyval = arr[i].split("=", 2);
obj[keyval[0]] = keyval[1];
}
return obj;
};
var objToString = function (obj) {
var stringBuilder = [];
for (var k in obj) {
stringBuilder.push(k+"="+obj[k]);
}
return stringBuilder.join(",");
};
var merge = function (obj1, obj2) { // merge obj1 into obj2.. obj2 will be modified.
for (var k in obj1) {
obj2[k] = obj2[k] || obj1[k];
}
return obj2;
};
var newStr = objToString(merge(toObj(str1), toObj(str2));
我很无聊,所以我决定对这三种不同的解决方案进行快速基准测试。
基准测试功能/测试:
function benchmark(name, fn, n) {
console.time(name);
for(var i = 0; i < n; i++)
fn();
console.timeEnd(name);
}
Andres(OP):
benchmark("Andres", function () { paramStrAndres("width=800,height=600,resizable=no,titlebar=no", "width=100,height=100"); }, 10000);
Andres: 505ms
瑞恩/ RWT:
benchmark("RWT", function () { paramStrRWT("width=800,height=600,resizable=no,titlebar=no", "width=100,height=100"); }, 10000);
RWT: 86ms
丹尼尔:
benchmark("Daniel", function () { paramStrDaniel("width=800,height=600,resizable=no,titlebar=no", "width=100,height=100"); }, 10000);
Daniel: 98ms
肖恩:
benchmark("Sean", function () { paramStrSean("width=800,height=600,resizable=no,titlebar=no", "width=100,height=100"); }, 10000);
Sean: 40ms
安德烈:
function paramStrAndres(str1, str2) {
sArray = str2.split(",");
for( var i = 0; i < sArray.length; i++ ) {
var key = sArray[i].match(/(\w+)=/gi).toString().replace("=", ""),
in_str1 = str1.search(key),
replace_pattern = new RegExp(key+"=(\\w+)", "gi");
if(in_str1 !== -1){
str1 = str1.replace(replace_pattern, sArray[i]);
} else {
str1 = str1 + "," + sArray[i];
}
}
return str1;
}
瑞恩/ RWT:
function paramStrRWT (str1, str2) {
function parseParamString(str, obj) {
var pairs = str.split(","),
i = 0, l = pairs.length,
pair;
obj || (obj = {});
for (; l > i; ++i) {
pair = pairs[i].split("=", 2);
obj[pair[0]] = pair[1];
}
return obj;
}
function buildParamString(obj) {
var pairs = [], i;
for (i in obj) {
if (obj.hasOwnProperty(i)) {
pairs.push(i + "=" + obj[i]);
}
}
return pairs.join(",");
}
var resultObj = parseParamString(str2, parseParamString(str1));
return buildParamString(resultObj);
}
矿:
function paramStrDaniel(str1, str2) {
var toObj = function (str) {
var arr = str.split(","), obj = {};
for (var i = 0; i < arr.length; i++) {
var keyval = arr[i].split("=", 2);
obj[keyval[0]] = keyval[1];
}
return obj;
};
var objToString = function (obj) {
var stringBuilder = [];
for (var k in obj) {
stringBuilder.push(k+"="+obj[k]);
}
return stringBuilder.join(",");
};
var merge = function (obj1, obj2) { // merge obj1 into obj2.. obj2 will be modified.
for (var k in obj1) {
obj2[k] = obj2[k] || obj1[k];
}
return obj2;
};
return objToString(merge(toObj(str1), toObj(str2)));
}
肖恩:
function paramStrSean(str1, str2) {
var str3 = str2 + "," + str1, temp;
while ((temp = str3.replace(/\b([a-z]+)(=.*)\b\1=[^,]*,?/, "$1$2")) != str3) {
str3 = temp;
}
return str3;
}
编辑:我觉得奇怪的是我的版本比Ryan快,因为它们相似。看了之后,我看到我在for循环中做了一个boo-boo(length -> arr.length
)。我更新了基准测试。这就是我没有测试我的代码所得到的。