0

I have a string like:

Id=bzat4e&Name=Gallery: Blitzer: Algebra & Trigonometry, 4e&Year=2016&Code=bzat4e

and I want to split it on the basis of &, while allowing the & inside values.

Basically it is a string of url parameters and I am fetching the value on the basis of key in my JavaScript.

I/P 
var paramList = Id=bzat4e&Name=Gallery: Blitzer: Algebra & Trigonometry, 4e&Year=2016&Code=bzat4e

O/P
[Id="bzat4e", Name="Gallery: Blitzer: Algebra & Trigonometry, 4e", Year="2016", Code="bzat4e"]
timolawl
  • 4,934
  • 9
  • 28
A_01
  • 711
  • 7
  • 22
  • 1
    Note that a 'literal' & in a url param must be encoded with %26. – Casimir et Hippolyte May 19 '16 at 11:38
  • Yeah it is, Basically I am fetching the string using var paramList = decodeURIComponent(window.location.search.substring(1)) – A_01 May 19 '16 at 11:40
  • @A_01: If you could include the `window.location` in the post, it would really help us in helping you. – AKS May 19 '16 at 11:47
  • 1
    Do you want JS to read your mind in order to decide which `&` are data and which ones are delimiters? Otherwise, how do you expect it to know? – Oriol May 19 '16 at 11:47

4 Answers4

2

You can use split() to get it as an array

var str = 'Id=bzat4e&Name=Gallery: Blitzer: Algebra & Trigonometry, 4e&Year=2016&Code=bzat4e';
var res = str.split(/&(?=[^=&]+=)/);
console.log(res);

To convert the array to an object use reduce()

var str = 'Id=bzat4e&Name=Gallery: Blitzer: Algebra & Trigonometry, 4e&Year=2016&Code=bzat4e';
var res = str.split(/&(?=[^=&]+=)/).reduce(function(a, b) {
  var spl = b.split('=');
  a[spl[0].trim()] = spl[1];
  return a;
}, {});
console.log(res);

For old browser check polyfill option for reduce() method.


Regex explanation here

Regular expression visualization

Pranav C Balan
  • 106,305
  • 21
  • 136
  • 157
  • No luck man. It creates 2 key-value pair. Like this "Name": "Gallery: Blitzer: Algebra ", "Trigonometry, 4e": undefined, which I dont want – A_01 May 19 '16 at 11:44
1

Edit: Not sure why I didn't think of this earlier:

var arr = paramList.split(/\b&\b/);

Try it out below:

var paramList = "Id=bzat4e&Name=Gallery: Blitzer: Algebra & Trigonometry, 4e&Year=2016&Code=bzat4e";

var arr = paramList.split(/\b&\b/);
var finalArr = [];

arr.forEach(function(pair) {
  var values = pair.split('=');
  var key = values[0];
  var value = values[1];
  var obj = {};
  obj[key] = value;
  finalArr.push(obj);
});

console.log(arr);

console.log(finalArr);
timolawl
  • 4,934
  • 9
  • 28
  • failing for i/p classId=sandbox-bzat4e&bltiRequestClassName=Gallery: Blitzer: Algebra &Trigonometry, 4e&schoolYear=2016&bookCode=bzat4e – A_01 May 19 '16 at 12:57
  • @A_01 Yeah it has the same issue, just without the needless extra characters. Let me generate a solution right now. – timolawl May 19 '16 at 13:03
  • @A_01 if every instance of your `&` that you wish to split out is always between word boundaries, you can change the regex to simply `\b&\b`. See my updated my answer. – timolawl May 19 '16 at 13:08
1

The solution for your particular input string using String.split function:

var str = "Id=bzat4e&Name=Gallery: Blitzer: Algebra & Trigonometry, 4e&Year=2016&Code=bzat4e",
    result = str.split(/(?!\s)[&](?!\s)/);

// now result contains 4 items
console.log(result);  // ["Id=bzat4e","Name=Gallery: Blitzer: Algebra & Trigonometry, 4e","Year=2016","Code=bzat4e"]
RomanPerekhrest
  • 73,078
  • 4
  • 37
  • 76
  • Your solution is working fine. Thanks man. Also I saw some has replied a solution like : split(/&(?!\s)/) but he removed that one not sure why but his solution is working as well – A_01 May 19 '16 at 11:57
  • I haven't seen that. It doesn't work for you? Maybe, you're testing it on another input string? – RomanPerekhrest May 19 '16 at 12:00
  • @A_01 That was me. I didn't know if you wanted your solution converted to objects as well, so I removed it. I put it back up with an object solution as well. – timolawl May 19 '16 at 12:01
1

You can use a RegEx to split the string, something like -

/(?!\s)&(?!\s)/g

This will split your string based on the "&" character, provided that there are no blank spaces around it.

Check out RegEx101 for a simple online RegEx editor.

Merlin
  • 171
  • 1
  • 5
  • 1
    @A_01 the `(?!\s)` before the `&` actually doesn't prevent a space in front from negating the match. https://regex101.com/r/wR1tJ4/1, which is why I didn't include it. – timolawl May 19 '16 at 12:04
  • @Merlin Thank you for the explanation also can you please lemme know good site/tutorial to learn it. Because I was struggling to create correct regex from past 2 hours on RegEx101 itself :) – A_01 May 19 '16 at 12:04
  • 1
    @A_01 regular-expressions.info. If that's too much, regexr.com has a small reference that I found helpful when I first started learning regex. SO has a lot of resources as well on regex: http://stackoverflow.com/a/2759417/5812121 http://stackoverflow.com/a/22944075/5812121 – timolawl May 19 '16 at 12:11
  • this fails if there is no space after `&`, for eg : `Id=bzat4e&Name=Gallery: Blitzer: AAlgebra &Trigonometry,` – Pranav C Balan May 19 '16 at 12:22
  • 1
    @A_01 In my opinion, the best way to learn RegEx is to actually write RegEx. Here's an exercise to get you started: try writing a RegEx to validate a phone number. Each country has its own rules, but basically once you understand the logic, it all fits nicely to a pattern. That's what RegEx is all about, finding patterns. Use [regex101](https://regex101.com) for a quick and intuitive RegEx editor. Other then that, Google is your best buddy for RegEx info – Merlin May 19 '16 at 12:39
  • Yeah it seems it will not work in scenerio like "classId=sandbox-bzat4e&bltiRequestClassName=Gallery: Blitzer: Algebra &Trigonometry, 4e&schoolYear=2016&bookCode=bzat4e" No space between "&Trigno". – A_01 May 19 '16 at 12:49
  • @A_01 Of course not, the pattern is blank space, followed by a "&" character, followed by another blank space. If the pattern changes, you need to change the RegEx. – Merlin May 19 '16 at 12:51