2

I need some help with extracting values from a cookie using javascript.

The string in a cookie looks something like this:

string = 'id=1||price=500||name=Item name||shipping=0||quantity=2++id=2||price=1500||name=Some other name||shipping=10||quantity=2'

By using string.split() and string.replace() and a some ugly looking code I've somehow managed to get the values i need (price, name, shipping, quantity). But the problem is that sometimes not all of the strings in the cookie are the same. Sometimes the sting in a cookie will look something like this :

   string = 'id=c1||color=red||size=XL||price=500||name=Item name||shipping=0||quantity=2++id=c1||price=500||name=Item name||shipping=0||quantity=2'

with some items having color and size as parameters and sometimes only one of those.

Is there some more efficient way to explain to my computer that i want the part of the string after 'price=' to be a variable named 'price' etc.

I hope I'm making sense I've tried to be as precise as I could.

Anyway, thank you for any help

EDIT: I just wanted to say thanks to all the great people of StackOverflow for such wonderfull ideas. Because of all of your great suggestions I'm going out to get drunk tonight. Thank you all :)

Slavenko Miljic
  • 3,751
  • 2
  • 19
  • 34
  • 2
    I think most people have missed the fact that there are 2 records in your string separated by `++`. How do you handle this? Do you just want the first price/name/etc? or both? – Jamiec Sep 09 '11 at 15:34

13 Answers13

9

Let's write a parser!

function parse(input)
{
    function parseSingle(input)
    {
        var parts = input.split('||'),
            part,
            record = {};

        for (var i=0; i<parts.length; i++)
        {
            part = parts[i].split('=');
            record[part[0]] = part[1];
        }

        return record;
    }

    var parts = input.split('++'),
        records = [];

    for (var i=0; i<parts.length; i++)
    {
        records.push(parseSingle(parts[i]));
    }

    return records;
}

Usage:

var string = 'id=1||price=500||name=Item name||shipping=0||quantity=2++id=2||price=1500||name=Some other name||shipping=10||quantity=2';

var parsed = parse(string);
/* parsed is:
[{id: "1", price: "500", name: "Item name", shipping: "0", quantity: "2"},
 {id: "2", price: "1500", name: "Some other name",  shipping: "10", quantity: "2"}]
*/
Matt Ball
  • 332,322
  • 92
  • 617
  • 683
3

You can achieve this using regular expressions. For example, the regex /price=([0-9]+)/ will match price=XXX where XXX is one or more numbers. As this part of the regex is surrounded by parenthesis it explicitly captures the numeric part for you.

var string = 'id=1||price=500||name=Item name||shipping=0||quantity=2++id=2||price=1500||name=Some other name||shipping=10||quantity=2'

var priceRegex = /price=([0-9]+)/
var match = string.match(priceRegex);
console.log(match[1]); // writes 500 to the console log
Jamiec
  • 118,012
  • 12
  • 125
  • 175
2

Try that:

var string = 'id=1||price=500||name=Item name||shipping=0||quantity=2++id=2||price=1500||name=Some other name||shipping=10||quantity=2';
var obj = new Array();
var arr = string.split('||');
for(var x=0; x<arr.length;x++){
    var temp = arr[x].split('=');
    obj[temp[0]] = temp[1]
}

alert(obj['id']); // alert 1
David Laberge
  • 13,061
  • 14
  • 51
  • 82
2

First, split your string into two (or more) parts by ++ separator:

var strings = myString.split('++');

then for each of the strings you want an object, right? So you need to have an array and fill it like that:

var objects = [];

for (var i = 0; i < strings.length; ++i) {
    var properties = strings[i].split('||');
    var obj = {};
    for (var j = 0; j < properties.length; ++j) {
          var prop = properties[j].split('=');
          obj[prop[0]] = prop[1]; //here you add property to your object, no matter what its name is
    }
    objects.push(obj);
}

thus you have an array of all objects constructed from your string. Naturally, in real life I'd add some checks that strings indeed satisfy the format etc. But the idea is clear, I hope.

Michael Sagalovich
  • 2,479
  • 18
  • 24
1

If you can replace the || with &, you could try to parse it as if it were a query string. A personal note - JSON-formatted data would've been easier to work with.

Community
  • 1
  • 1
1

I would attach the data to a javascript object.

  var settingsObj = {};
  var components = thatString.split('||');

  for(var j = 0; j < components.length; j++)
  {
       var keyValue = components[j].split('=');

       settingsObj[keyValue[0]] = keyValue[1];
  }

  // Now the key value pairs have been set, you can simply request them

  var id = settingsObj.id; // 1 or c1
  var name = settingsObj.name; // Item Name, etc
Tejs
  • 38,896
  • 8
  • 64
  • 81
1

You're already using .split() to break down the string by || just take that a step further and split each of those sections by = and assign everything on the left the field and the right the value

Exupery
  • 3,070
  • 4
  • 36
  • 48
1

This should get the first match in the string:

string.match(/price=(\d{1,})/)[1]

Note this will only match the first price= in the string, not the second one.

Michael Irwin
  • 3,031
  • 5
  • 21
  • 35
1

If you can use jQuery, it wraps working with cookies and lets you access them like:

Reading a cookie: var comments = $.cookie('comments');

Writing a cookie: $.cookie('comments', 'expanded');

This post by someone else has a decent example: http://www.vagrantradio.com/2009/10/getting-and-setting-cookies-with-jquery.html

If you can't use jQuery, you need to do standard string parsing like you currently are (perhaps regular expressions instead of the string splitting / replacing might trim down your code) or find some other javascript library that you can use.

jminadeo
  • 55
  • 5
1

If you like eye candies in your code you can use a regexp based "search and don't replace" trick by John Resig (cached here) :

var extract = function(string) {
    var o = {};

    string.replace(/(.*?)=(.*?)(?:\|\||$)/g, function(all, key, value) {
        o[key] = value;
    });

    return o;
};

Then

var objects = string.split('++'), 
    i = objects.length;

for (;i--;) {
    objects[i] = extract(objects[i]);
}
Placoplatr
  • 480
  • 2
  • 12
0
var str = 'id=c1||color=red||size=XL||price=500||name=Item name||shipping=0||quantity=2++id=c1||price=500||name=Item name||shipping=0||quantity=2'
var items = str.split("++");
for (var i=0; i<items.length; i++) {
    var data = items[i].split("||");
    for (var j=0; j<data.length; j++) {
        var stuff = data[j].split("=");
        var n = stuff[0]; 
        var v = stuff[1];
        eval("var "+n+"='"+v+"'");
    }
    alert(id);
}

EDIT: As per JamieC's suggestion, you can eliminate eval("var "+n+"='"+v+"'"); and replace it with the (somewhat) safer window[n] = v; -- but you still have the simple problem that this will overwrite existing variables, not to mention you can't tell if the variable color was set on this iteration or if this one skipped it and the last one set it. Creating an empty object before the loop and populating it inside the loop (like every other answer suggests) is a better approach in almost every way.

Blazemonger
  • 82,329
  • 24
  • 132
  • 176
  • I agree, but it's what the question asked for. – Blazemonger Sep 09 '11 at 15:34
  • http://net.tutsplus.com/tutorials/javascript-ajax/the-10-javascript-mistakes-youre-making/ - see mistake 6 – Michael Sagalovich Sep 09 '11 at 15:35
  • @mblase - really? Where did the OP ask for a solution involving `eval`? – Jamiec Sep 09 '11 at 15:35
  • nobody is 'building an associative array' here, we are building the object. Surprisingly, all objects in JS are key/value pairs (associative arrays). ALL OBJECTS, I SAY. – Michael Sagalovich Sep 09 '11 at 15:44
  • We quibble over terms. It walks like an associative array and quacks like an associative array, so I call it an associative array. – Blazemonger Sep 09 '11 at 15:48
  • by the way, in case you're interested you dont need the eval at all. Seeing as you're putting everything in global scope anyway you may as well do `window[n] = v`. But you've made the same mistake as everyone and forgotton about the `++` delimiting records. – Jamiec Sep 09 '11 at 15:52
  • Check my code again; I split on "++" before doing anything else. Good point about using `window[n]`; I didn't know that variables could be set that way. – Blazemonger Sep 09 '11 at 16:33
0

You could do something like this, where you eval the strings when you split them.

<html>
<head>
<script type="text/javascript">
var string = 'id=c1||color=red||size=XL||price=500||name=Item name||shipping=0||quantity=2++id=c1||price=500||name=Item name||shipping=0||quantity=2'


var mySplitResult = string.split("||");

for(i = 0; i < mySplitResult.length; i++){
    document.write("<br /> Element " + i + " = " + mySplitResult[i]); 
    var assignment = mySplitResult[i].split("=");

    eval(assignment[0] + "=" + "\""+assignment[1]+"\"");
}
document.write("Price : " + price);
</script>
</head>
<body>
</body>
</html>
Mike K.
  • 3,581
  • 24
  • 41
0
JSON.parse('[{' + string.replace(/\+\+/g, '},{').replace(/(\w*)=([\w\s]*)/g, '"$1":"$2"').replace(/\|\|/g, ',') + '}]')

Convert the string for JSON format, then parse it.