Объединение двух строк пар ключ = значение в JavaScript - PullRequest
5 голосов
/ 04 августа 2010

Я пытаюсь найти эффективный способ перезаписи 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];
    }
}

Ответы [ 3 ]

7 голосов
/ 04 августа 2010

Вот довольно краткое решение на основе регулярных выражений:

str3 = str2 + "," + str1;

while ((temp = str3.replace(/\b([a-z]+)(=.*)\b\1=[^,]*,?/, "$1$2")) != str3) {
    str3 = temp;
}

Оно работает, добавляя переопределяющую строку к перезаписываемой строке, затем многократно удаляя дубликаты, которые появляются позже в объединенной строке, до тех пор, покаany.

Потребуется немного больше внимания, если строка может быть пустой, или разрешен какой-либо вид экранирования, или если ключи могут быть названы иначе, чем только буквами.

2 голосов
/ 04 августа 2010

Я придумал следующее, но я не уверен, будет ли это быстрее, чем ваш метод, так как требуется еще несколько шагов.Кроме того, это немного дольше ...

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);  
}

Результаты:

Андрес (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;
    }

РЕДАКТИРОВАТЬ : мне показалось странным, что моя версия былабыстрее, чем у Райана, учитывая, что они были похожи.Посмотрев его, я вижу, что я сделал бу-бу на цикле for (length -> arr.length).Я обновил тесты.Вот что я получаю за то, что не тестировал мой код.

2 голосов
/ 04 августа 2010

Не пытался запустить его, но это должно сработать, создал служебную функцию 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);

Редактировать: забыл о превращении объекта обратно в строку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...